From: Tatsuki Sugiura Date: 2005-11-17T19:48:06+09:00 Subject: [ruby-dev:27729] Thread deadlock when signale handler raise exception こんにちは。杉浦です。 いまいち絞れないのですが、デッドロックする状況を見つけました。 単に私のやり方が悪いのかもと思ったのですが、入出力を伴うと現象が変わる と言う不思議な状況なので、多分バグだろうと言うことでレポートします。 整理できていないので長いですがご勘弁下さい。 ruby 1.8.4 (2005-10-29) [i486-linux] で確認しています。 以下の状況 * スレッドが2つ以上あって * trap に exit するか、例外を起こすブロック(proc)を渡しておく で、シグナルハンドラが呼ばれるとデッドロックしてしまいます。 最初に見つけたのは ------------------------------------------ require 'timeout' require 'thread' trap(:INT){ puts "INT" # <=== exit } timeout(3) { Queue.new.pop } ------------------------------------------ と言うコードです。これを実行して(3秒たつ前に)Ctrl+c を押すと、 sugi@tempest:~% ruby queue-timeout.rb INT で止まってずっと帰ってきません。もう一度 Ctrl+c を押すと、"INT" が 再度出力されてプロンプトに戻ります。 ところが # <=== の puts を削ると状況が変わります。 1回だけ Ctrl+c を押して暫く待つと、 sugi@tempest:~% ruby -v queue-timeout.rb ruby 1.8.4 (2005-10-29) [i486-linux] /usr/lib/ruby/1.8/timeout.rb:43: execution expired (Timeout::Error) from /usr/lib/ruby/1.8/timeout.rb:45:in `timeout' from /usr/lib/ruby/1.8/timeout.rb:62:in `timeout' from queue-timeout.rb:9 となってタイムアウトします。今度は2回 Ctrl+c を押して待つと、 sugi@tempest:~% ruby -v queue-timeout.rb ruby 1.8.4 (2005-10-29) [i486-linux] /usr/lib/ruby/1.8/timeout.rb:43:in `timeout': execution expired (Timeout::Error) from queue-timeout.rb:9 と言うもう少し違うトレースを表示してタイムアウトします。 3回押すと何も表示せずに終了します。 もう少し単純な(ライブラリを使わない)コードだと、 ------------------------------------------ require 'thread' trap(:INT) { puts "INT" # <=== (1) exit } begin t = Thread.start { sleep } sleep ensure # STDOUT.flush # <=== (2) t.kill # <=== (3) end ------------------------------------------ は同じく Ctrl+c を1回押しても止まりません(2回で止まります)。 ところが、(1)〜(3) で示されている行をコメントアウトしたり 外したりすると色々状況が変わります。 以下の時は1回で止まります: * (1) と (2) と (3) を全部実行 * (1) だけ実行 * (1) と (2) を実行 2回必要なのは以下の時です: * (1) (2) (3) を全部コメントアウト * (2) だけ実行 * (3) だけ実行 * (1) と (3) を実行 * (2) と (3) を実行 それから、2つのサンプルは exit を raise に変えても同じ状況に なりますが、trap の中で trap(:INT) { Thread.new { Thread.pass; Thread.main.raise SystemExit } } とするとどちらも Ctrl+c 1回で終了するようです。 また、trap :INT, "EXIT" ならすぐに終了します。 -- Tatsuki Sugiura mailto:sugi@nemui.org