1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

merge revision(s) 44517,44518,44519,44523: [Backport #9354]

* lib/timeout.rb (Timeout#timeout): when a custom exception is given,
	  no instance is needed to be caught, so defer creating new instance
	  until it is raised.  [ruby-core:59511] [Bug #9354]

	* lib/timeout.rb (Timeout#timeout): should not rescue ordinarily
	  raised ExitException, which should not be thrown.

	* lib/timeout.rb (Timeout::ExitException.catch): set @thread only if
	  it ought to be caught.

	* lib/timeout.rb (Timeout::ExitException.catch): pass arguments
	  for new instance.

	* lib/timeout.rb (Timeout::ExitException#exception): fallback to
	  Timeout::Error if couldn't throw.  [ruby-dev:47872] [Bug #9380]

	* lib/timeout.rb (Timeout#timeout): initialize ExitException with
	  message for the fallback case.


git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_2_1@44841 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
naruse 2014-02-05 12:43:19 +00:00
parent c0bdb2511d
commit c00e288936
4 changed files with 78 additions and 10 deletions

View file

@ -1,3 +1,26 @@
Wed Feb 5 21:12:02 2014 Nobuyoshi Nakada <nobu@ruby-lang.org>
* lib/timeout.rb (Timeout::ExitException.catch): pass arguments
for new instance.
* lib/timeout.rb (Timeout::ExitException#exception): fallback to
Timeout::Error if couldn't throw. [ruby-dev:47872] [Bug #9380]
* lib/timeout.rb (Timeout#timeout): initialize ExitException with
message for the fallback case.
Wed Feb 5 21:12:02 2014 Nobuyoshi Nakada <nobu@ruby-lang.org>
* lib/timeout.rb (Timeout#timeout): should not rescue ordinarily
raised ExitException, which should not be thrown.
* lib/timeout.rb (Timeout::ExitException.catch): set @thread only if
it ought to be caught.
* lib/timeout.rb (Timeout#timeout): when a custom exception is given,
no instance is needed to be caught, so defer creating new instance
until it is raised. [ruby-core:59511] [Bug #9354]
Wed Feb 5 17:55:28 2014 Aman Gupta <ruby@tmm1.net> Wed Feb 5 17:55:28 2014 Aman Gupta <ruby@tmm1.net>
* array.c (ary_add_hash): Fix consistency issue between Array#uniq and * array.c (ary_add_hash): Fix consistency issue between Array#uniq and

View file

@ -26,16 +26,25 @@ module Timeout
class Error < RuntimeError class Error < RuntimeError
end end
class ExitException < ::Exception # :nodoc: class ExitException < ::Exception # :nodoc:
attr_reader :klass, :thread attr_reader :thread
def initialize(*) def self.catch(*args)
super exc = new(*args)
@thread = Thread.current exc.instance_variable_set(:@thread, Thread.current)
freeze exc.freeze
::Kernel.catch(exc) {yield exc}
end end
def exception(*) def exception(*)
throw(self, caller) if self.thread == Thread.current if self.thread == Thread.current
bt = caller
begin
throw(self, bt)
rescue ArgumentError => e
raise unless e.message.start_with?("uncaught throw")
raise Error, message, backtrace
end
end
self self
end end
end end
@ -67,7 +76,7 @@ module Timeout
return yield(sec) if sec == nil or sec.zero? return yield(sec) if sec == nil or sec.zero?
message = "execution expired" message = "execution expired"
e = Error e = Error
bt = catch((klass||ExitException).new) do |exception| bl = proc do |exception|
begin begin
x = Thread.current x = Thread.current
y = Thread.start { y = Thread.start {
@ -80,8 +89,6 @@ module Timeout
end end
} }
return yield(sec) return yield(sec)
rescue (klass||ExitException) => e
e.backtrace
ensure ensure
if y if y
y.kill y.kill
@ -89,6 +96,15 @@ module Timeout
end end
end end
end end
if klass
begin
bl.call(klass)
rescue klass => e
bt = e.backtrace
end
else
bt = ExitException.catch(message, &bl)
end
rej = /\A#{Regexp.quote(__FILE__)}:#{__LINE__-4}\z/o rej = /\A#{Regexp.quote(__FILE__)}:#{__LINE__-4}\z/o
bt.reject! {|m| rej =~ m} bt.reject! {|m| rej =~ m}
level = -caller(CALLER_OFFSET).size level = -caller(CALLER_OFFSET).size

View file

@ -57,4 +57,33 @@ class TestTimeout < Test::Unit::TestCase
end end
assert_raise_with_message(exc, /execution expired/) {raise e if e} assert_raise_with_message(exc, /execution expired/) {raise e if e}
end end
def test_custom_exception
bug9354 = '[ruby-core:59511] [Bug #9354]'
err = Class.new(StandardError) do
def initialize(msg) super end
end
assert_nothing_raised(ArgumentError, bug9354) do
assert_equal(:ok, timeout(100, err) {:ok})
end
end
def test_exit_exception
assert_raise_with_message(Timeout::ExitException, "boon") do
Timeout.timeout(10, Timeout::ExitException) do
raise Timeout::ExitException, "boon"
end
end
end
def test_enumerator_next
bug9380 = '[ruby-dev:47872] [Bug #9380]: timeout in Enumerator#next'
e = (o=Object.new).to_enum
def o.each
sleep
end
assert_raise_with_message(Timeout::Error, 'execution expired', bug9380) do
Timeout.timeout(0.01) {e.next}
end
end
end end

View file

@ -1,6 +1,6 @@
#define RUBY_VERSION "2.1.1" #define RUBY_VERSION "2.1.1"
#define RUBY_RELEASE_DATE "2014-02-05" #define RUBY_RELEASE_DATE "2014-02-05"
#define RUBY_PATCHLEVEL 18 #define RUBY_PATCHLEVEL 19
#define RUBY_RELEASE_YEAR 2014 #define RUBY_RELEASE_YEAR 2014
#define RUBY_RELEASE_MONTH 2 #define RUBY_RELEASE_MONTH 2