@@ -26,6 +26,18 @@ module Timeout
2626 class Error < RuntimeError
2727 end
2828 class ExitException < ::Exception # :nodoc:
29+ attr_reader :klass , :thread
30+
31+ def initialize ( *)
32+ super
33+ @thread = Thread . current
34+ freeze
35+ end
36+
37+ def exception ( *)
38+ throw ( self , caller ) if self . thread == Thread . current
39+ self
40+ end
2941 end
3042
3143 # :stopdoc:
@@ -50,8 +62,7 @@ class ExitException < ::Exception # :nodoc:
5062 # a module method, so you can call it directly as Timeout.timeout().
5163 def timeout ( sec , klass = nil ) #:yield: +sec+
5264 return yield ( sec ) if sec == nil or sec . zero?
53- exception = klass || Class . new ( ExitException )
54- begin
65+ bt = catch ( ExitException . new ) do |exception |
5566 begin
5667 x = Thread . current
5768 y = Thread . start {
@@ -60,7 +71,8 @@ def timeout(sec, klass = nil) #:yield: +sec+
6071 rescue => e
6172 x . raise e
6273 else
63- x . raise exception , "execution expired"
74+ # no message, not to make new instance.
75+ x . raise exception
6476 end
6577 }
6678 return yield ( sec )
@@ -70,18 +82,14 @@ def timeout(sec, klass = nil) #:yield: +sec+
7082 y . join # make sure y is dead.
7183 end
7284 end
73- rescue exception => e
74- rej = /\A #{ Regexp . quote ( __FILE__ ) } :#{ __LINE__ -4 } \z /o
75- ( bt = e . backtrace ) . reject! { |m | rej =~ m }
76- level = -caller ( CALLER_OFFSET ) . size
77- while THIS_FILE =~ bt [ level ]
78- bt . delete_at ( level )
79- level += 1
80- end
81- raise if klass # if exception class is specified, it
82- # would be expected outside.
83- raise Error , e . message , e . backtrace
8485 end
86+ rej = /\A #{ Regexp . quote ( __FILE__ ) } :#{ __LINE__ -4 } \z /o
87+ bt . reject! { |m | rej =~ m }
88+ level = -caller ( CALLER_OFFSET ) . size
89+ while THIS_FILE =~ bt [ level ]
90+ bt . delete_at ( level )
91+ end
92+ raise ( ( klass ||Error ) , "execution expired" , bt )
8593 end
8694
8795 module_function :timeout
0 commit comments