From: "kosaki (Motohiro KOSAKI)" Date: 2012-11-26T12:27:29+09:00 Subject: [ruby-dev:46626] [ruby-trunk - Bug #5368] ensure節でsleepするようなThreadがあるとインタプリタが終了しない Issue #5368 has been updated by kosaki (Motohiro KOSAKI). 読み返しました。[Feature #1952] とちょっと似た話で終了途中で例外食われてしまったら、という話のようですね。論点をまとめると - ensure節の中でsleep等、無限待ちが記述されているとハングしてしまう。これはバグではないか (Glass_saga) - この場合止まっているのはサブスレッドなので、Ctrl-cは意味が無い。メインスレッドが食って無視してしまう - しかし、タイムアウト等をつくると終了処理に時間のかかるスクリプトが壊れてしまう (ko1) - ensure節実行中にterminateされたらensure抜けてしまうので言語仕様としてつじつまがあってない (高尾さん) - sleepで寝ていても、もう一度例外が上がってきたら抜けるべきでは? (← これよくわからないが Ctrl-Cうけたらメインスレッドがthread terminateを再送しろということ?) - Ctrl-c 二連打で、終了処理がスッポ抜けるのって本当にうれしい?(こさき) - 現在、main threadがsub threadの終了を待つロジックがビジーループなのでCPU100%になってしまう。スレッドが終了するまでちゃんと寝るべきではないのか (やや脱線) ぐらいですかね。 ---------------------------------------- Bug #5368: ensure節でsleepするようなThreadがあるとインタプリタが終了しない https://bugs.ruby-lang.org/issues/5368#change-33934 Author: Glass_saga (Masaki Matsushita) Status: Assigned Priority: High Assignee: kosaki (Motohiro KOSAKI) Category: core Target version: 2.0.0 ruby -v: - =begin 次のコードを実行するとCPU使用率が跳ね上がった状態になりインタプリタが終了しません。 Thread.new do begin sleep ensure sleep end end 現在のrb_thread_terminate_allでは最初に1回だけ生きているスレッドに対してterminate_iを実行していますが、ensure節でsleepするようなThreadがあると、そのThreadは寝たままになってしまいwhile(!rb_thread_alone())が無限ループになってしまいます。 while(!rb_thread_alone())の毎回のループでカレントスレッドがメインスレッドであった場合に、生きているスレッドに対してterminate_iを実行するようなpatchを書いたところ、このバグは再現しなくなりました。 patchを添付します。patchの適用後もtest-allをパスします。 =end -- http://bugs.ruby-lang.org/