Ruby Timeout ведет себя по-разному между 2.0 и 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

В рубине 2.0 это дает:

In begin
Exception found: execution expired
In ensure

В рубине 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>'

Почему они разные?


person WKPlus    schedule 17.02.2016    source источник
comment
Я тестирую Ruby 2.2.3 в Linux и получаю то же поведение, что и ваш Ruby 2.1. Я также вижу, что Timeout::Error.new.is_a?(Exception) равно true.   -  person David Grayson    schedule 17.02.2016


Ответы (1)


Это задокументированное поведение. Мы можем сравнить документацию модуля Ruby Timeout для 2.0.0. и для 2.1.0 . В документации для 2.1.0 говорится:

Исключение, созданное для завершения данного блока, не может быть спасено внутри блока, если класс не указан явно.

Если вы хотите сохранить старое поведение в своем приложении, вы можете вызвать Timeout::timeout(1, Timeout::Error). Это позволит вам поймать исключение внутри временного блока.

person David Grayson    schedule 17.02.2016
comment
Как странно. Это изменение особо не комментировалось. Я не уверен, что это действительно сильно помогает. Мне любопытно посмотреть, имеет ли последний JRuby 9k поведение 2.1.0... - person jrochkind; 17.02.2016