From: "nagachika (Tomoyuki Chikanaga)" Date: 2012-12-19T02:31:08+09:00 Subject: [ruby-dev:46762] [ruby-trunk - Bug #5993][Assigned] Thread.new{ Fiber.new { Thread.exit }.resume }.join で例外 Issue #5993 has been updated by nagachika (Tomoyuki Chikanaga). File thread_exit_in_fiber.patch added Status changed from Open to Assigned パッチを作り直しました。 rb_threadptr_execute_interrupts() で async_errinfo_queue から INT2FIX(TAG_FATAL) が取れる可能性を考慮するようにしました。通常は INT2FIX(TAG_FATAL) は rb_threadptr_to_kill() で発生させて同期的例外のように処理するので async_errinfo_queue に入ることはないはずですが、Fiberの終了時は fiber_terminate()して Fiber を切り替えるまで遅延させるために例外的に async_errinfo_queue に入ることがあります。というか入れるようにしました。 そのかわり r38441 で rb_vm_make_jump_tag_but_local_jump() で TAG_FATAL を考慮するようにした変更は revert しています。 手元では make check は通りました。よさそうだったらコミットします。 ---------------------------------------- Bug #5993: Thread.new{ Fiber.new { Thread.exit }.resume }.join で例外 https://bugs.ruby-lang.org/issues/5993#change-34833 Author: nagachika (Tomoyuki Chikanaga) Status: Assigned Priority: Normal Assignee: nagachika (Tomoyuki Chikanaga) Category: core Target version: 2.0.0 ruby -v: ruby 2.0.0dev (2012-02-09 trunk 34514) [x86_64-darwin10.8.0] 以下のように Fiber 内で Thread.exit するとメッセージが空の RuntimeError が発生します。 Thread.new{ Fiber.new { Thread.exit }.resume }.join #=> RuntimeError: rb_fiber_start() で Thread.exit 時の TAG_FATAL での TAG_JUMP を想定していないためだと思います。とりあえず以下のようにすると例外にならなくなります。 あと th->errinfo は空を Qnil としているのに th->thrown_errinfo は 0 (Qfalse)を空であることを示すのに使っているので、その食い違いで thrown_errinfo に Qnil を入れてしまっていた(rb_vm_make_jump_tag_but_local_jump() の結果が Qnil の時)のが原因のようなので、そちらをなんとかすべきかもしれません。全体的に thrown_errinfo も空を意味するために Qnil を使うようにそろえるとか? --- a/cont.c +++ b/cont.c @@ -1152,6 +1152,9 @@ rb_fiber_start(void) if (state == TAG_RAISE) { th->thrown_errinfo = th->errinfo; } + else if (state == TAG_FATAL && th->errinfo == INT2FIX(TAG_FATAL)) { + /* terminating */ + } else { th->thrown_errinfo = rb_vm_make_jump_tag_but_local_jump(state, th->errinfo); -- http://bugs.ruby-lang.org/