👏

[Bug #20314] Timeout.timeout がネストしている場合に同じタイミングでタイムアウトが発生した場合のバグ報告

に公開

[Bug #20314] Simultaneous Timeout expires may raise an exception after the block

  • 同じタイミングでタイムアウトが発生すると rescue した後に例外が発生するバグ報告
  • どういうことかというと次のように同じ時刻で Timeout.timeout がネストしている場合に同時にタイムアウトが発生すると rescue でキャッチした後に例外が発生する
require "timeout"

class A < Exception
end

class B < Exception
end

begin
  Timeout.timeout(0.1, A) do
    Timeout.timeout(0.1, B) do
      nil while true
    end
  end
rescue A, B => e
  p $! #=> #<A: execution expired>

  # このタイミングで例外が発生する
  #=> test.rb:16:in `p': execution expired (B)

  p :end # ここには到達せず実行されない
end
  • Timeout.timeout がネストしているとこういう挙動になる可能性があるんですね
  • 修正案としては以下が提示されている
    1. 最も外側のタイムアウトで例外を発生させて、内側は例外を発生させないようにする
    2. 最も内側のタイムアウトで例外を発生させて、外側は例外を発生させないようにする
    3. Thread#raise(A) されている場合、新しい Thread#raise(B)A を処理するまでブロッキングする
  • 1.2. は書き方によっては永続的にブロッキングし続ける可能性がある可能性があるみたいですね
  • チケットは2年前のものなのですが、コメントを読む限りだと今の所これと言った解決策はなさそうみたい
  • 今は Timeout::ExitException can be raised by nested timeouts · Issue #52 · ruby/timeout の方で議論しているみたいですね?
GitHubで編集を提案

Discussion