Skip to content

Commit 1a3bcf1

Browse files
committed
timeout.rb: skip rescue
* lib/timeout.rb (Timeout#timeout): should not be caught by rescue clause. [Bug #8730] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@42690 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
1 parent c075b15 commit 1a3bcf1

3 files changed

Lines changed: 41 additions & 14 deletions

File tree

ChangeLog

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
Mon Aug 26 15:27:39 2013 Nobuyoshi Nakada <[email protected]>
2+
3+
* lib/timeout.rb (Timeout#timeout): should not be caught by rescue
4+
clause. [Bug #8730]
5+
16
Mon Aug 26 14:44:26 2013 Koichi Sasada <[email protected]>
27

38
* array.c (rb_ary_splice): use RARRAY_PTR_USE() without WB because

lib/timeout.rb

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -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

test/test_timeout.rb

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,4 +29,18 @@ def test_cannot_convert_into_time_interval
2929
def (n = Object.new).zero?; false; end
3030
assert_raise(TypeError, bug3168) {Timeout.timeout(n) { sleep 0.1 }}
3131
end
32+
33+
def test_skip_rescue
34+
bug8730 = '[Bug #8730]'
35+
e = nil
36+
assert_raise(Timeout::Error, bug8730) do
37+
timeout 0.1 do
38+
begin
39+
sleep 3
40+
rescue Exception => e
41+
end
42+
end
43+
end
44+
assert_nil(e, bug8730)
45+
end
3246
end

0 commit comments

Comments
 (0)