ruby-changes:30611
From: nobu <ko1@a...>
Date: Mon, 26 Aug 2013 15:27:56 +0900 (JST)
Subject: [ruby-changes:30611] nobu:r42690 (trunk): timeout.rb: skip rescue
nobu 2013-08-26 15:27:48 +0900 (Mon, 26 Aug 2013) New Revision: 42690 http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=42690 Log: timeout.rb: skip rescue * lib/timeout.rb (Timeout#timeout): should not be caught by rescue clause. [Bug #8730] Modified files: trunk/ChangeLog trunk/lib/timeout.rb trunk/test/test_timeout.rb Index: ChangeLog =================================================================== --- ChangeLog (revision 42689) +++ ChangeLog (revision 42690) @@ -1,3 +1,8 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1 +Mon Aug 26 15:27:39 2013 Nobuyoshi Nakada <nobu@r...> + + * lib/timeout.rb (Timeout#timeout): should not be caught by rescue + clause. [Bug #8730] + Mon Aug 26 14:44:26 2013 Koichi Sasada <ko1@a...> * array.c (rb_ary_splice): use RARRAY_PTR_USE() without WB because Index: lib/timeout.rb =================================================================== --- lib/timeout.rb (revision 42689) +++ lib/timeout.rb (revision 42690) @@ -26,6 +26,18 @@ module Timeout https://github.com/ruby/ruby/blob/trunk/lib/timeout.rb#L26 class Error < RuntimeError end class ExitException < ::Exception # :nodoc: + attr_reader :klass, :thread + + def initialize(*) + super + @thread = Thread.current + freeze + end + + def exception(*) + throw(self, caller) if self.thread == Thread.current + self + end end # :stopdoc: @@ -50,8 +62,7 @@ module Timeout https://github.com/ruby/ruby/blob/trunk/lib/timeout.rb#L62 # a module method, so you can call it directly as Timeout.timeout(). def timeout(sec, klass = nil) #:yield: +sec+ return yield(sec) if sec == nil or sec.zero? - exception = klass || Class.new(ExitException) - begin + bt = catch(ExitException.new) do |exception| begin x = Thread.current y = Thread.start { @@ -60,7 +71,8 @@ module Timeout https://github.com/ruby/ruby/blob/trunk/lib/timeout.rb#L71 rescue => e x.raise e else - x.raise exception, "execution expired" + # no message, not to make new instance. + x.raise exception end } return yield(sec) @@ -70,18 +82,14 @@ module Timeout https://github.com/ruby/ruby/blob/trunk/lib/timeout.rb#L82 y.join # make sure y is dead. end end - rescue exception => e - rej = /\A#{Regexp.quote(__FILE__)}:#{__LINE__-4}\z/o - (bt = e.backtrace).reject! {|m| rej =~ m} - level = -caller(CALLER_OFFSET).size - while THIS_FILE =~ bt[level] - bt.delete_at(level) - level += 1 - end - raise if klass # if exception class is specified, it - # would be expected outside. - raise Error, e.message, e.backtrace end + rej = /\A#{Regexp.quote(__FILE__)}:#{__LINE__-4}\z/o + bt.reject! {|m| rej =~ m} + level = -caller(CALLER_OFFSET).size + while THIS_FILE =~ bt[level] + bt.delete_at(level) + end + raise((klass||Error), "execution expired", bt) end module_function :timeout Index: test/test_timeout.rb =================================================================== --- test/test_timeout.rb (revision 42689) +++ test/test_timeout.rb (revision 42690) @@ -29,4 +29,18 @@ class TestTimeout < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/test_timeout.rb#L29 def (n = Object.new).zero?; false; end assert_raise(TypeError, bug3168) {Timeout.timeout(n) { sleep 0.1 }} end + + def test_skip_rescue + bug8730 = '[Bug #8730]' + e = nil + assert_raise(Timeout::Error, bug8730) do + timeout 0.1 do + begin + sleep 3 + rescue Exception => e + end + end + end + assert_nil(e, bug8730) + end end -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/