Timeout::ExitException can be raised by nested timeouts
まだ誰も着手していません。
- 主要言語
- Ruby
- スター
- 168
- フォーク
- 33
- 平均マージ
- 5時間 58分
- マージ済み PR(30日)
- 3
説明
Behavior
Nested timeout blocks can result in a Timeout::ExitException being raised, rather than a Timeout::Error
How to reproduce
The below will sometimes raise a Timeout::ExitException, sometimes a Timeout::Error (roughly 50/50).
begin
Timeout.timeout(2) do
Timeout.timeout(2) do
sleep 3
end
end
rescue Exception => e
puts "raised a #{e.class}"
end
Cause (maybe)
Hacking up the Timeout module as follows:
module Timeout
class Error
def self.handle_timeout(message) # :nodoc:
exc = ExitException.new(message)
begin
puts "yield #{exc.object_id} (#{message})"
yield exc
rescue ExitException => e
puts "test #{e.object_id} vs #{exc.object_id} => #{exc.equal?(e)} (#{message})"
raise new(message) if exc.equal?(e)
puts "re-raise #{e.object_id}('#{e}') (#{message})"
raise
end
end
end
end
Timeout.timeout(2, nil, "outer timeout") do
Timeout.timeout(2, nil, "inner timeout") do
sleep 3
end
end
shows that, when an ExitException is raised, the "inner" exception is being caught by the "outer" handle_timeout block. Suspicious this is the result of indeterminate Thread#raise behavior?
Environment
Ruby 3.3.5
Timeout 0.4.1
Ubuntu 24.04.1 running on WSL2
コントリビューションガイド
このリポジトリのコントリビューションガイドは索引されていません
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
調査の方向性
まず、issue にあるネストした Timeout.timeout の再現コードを実行し、Timeout.timeout の経路、特に Timeout::Error.handle_timeout と ExitException の処理を調査します。内部の例外が外側のハンドラーに到達できる条件を確認します。完了条件は、再現コードに対するリグレッションチェックを追加し、ネストしたタイムアウトが一貫して Timeout::ExitException ではなく Timeout::Error を発生させることです。
索引モデルが issue の本文から書いたものです。
評価
- 技術スタック
- ruby
- 領域
- backend
- issue の種類
- バグ
- 難易度
- 4/5
- 見積もり時間
- 3〜5日
- 活発さ
- 停滞
- 明瞭さ
- おおむね明確
- 初心者へのやさしさ
- 42/100