Ruby 2.0 和 2.1 之间的超时行为不同

Ruby Timeout behaves differently between 2.0 and 2.1

以下代码在 ruby 2.0 和 2.1 之间的行为不同:

require 'timeout'

def scp
  begin
    puts "In begin"
    sleep 10
  rescue Exception => e
    puts "Exception found: #{e}"
  else
    puts "No exception found"
  ensure
    puts "In ensure"
  end
end

Timeout::timeout(1) do
  scp
end

在 ruby 2.0 中,它给出:

In begin
Exception found: execution expired
In ensure

在 ruby 2.1 中,它给出:

In begin
In ensure
t2.rb:7:in `sleep': execution expired (Timeout::Error)
    from t2.rb:7:in `scp'
    from t2.rb:18:in `block in <main>'
    from /usr/local/rvm/rubies/ruby-2.1.2/lib/ruby/2.1.0/timeout.rb:91:in `block in timeout'
    from /usr/local/rvm/rubies/ruby-2.1.2/lib/ruby/2.1.0/timeout.rb:35:in `block in catch'
    from /usr/local/rvm/rubies/ruby-2.1.2/lib/ruby/2.1.0/timeout.rb:35:in `catch'
    from /usr/local/rvm/rubies/ruby-2.1.2/lib/ruby/2.1.0/timeout.rb:35:in `catch'
    from /usr/local/rvm/rubies/ruby-2.1.2/lib/ruby/2.1.0/timeout.rb:106:in `timeout'
    from t2.rb:17:in `<main>'

为什么不同?

这是记录在案的行为。我们可以比较一下 Ruby 的 Timeout 模块对 2.0.0 and for 2.1.0 的文档。 2.1.0 的文档说:

The exception thrown to terminate the given block cannot be rescued inside the block unless klass is given explicitly.

如果你想在你的应用程序中有旧的行为,你可以调用 Timeout::timeout(1, Timeout::Error)。这将允许您在定时块内捕获异常。