From: Masaki Matsushita Date: 2011-07-08T00:55:09+09:00 Subject: [ruby-dev:44050] [Ruby 1.9 - Bug #4988] ObjectSpace.#define_finalizer内でMutexをロックして解放しないまま抜けるとabortする Issue #4988 has been updated by Masaki Matsushita. 書いてしまってから気づきましたが、rb_thread_terminate_all()の前にfinalizerを呼ぶのは明らかに問題がありますね。 無知丸出しだなあ、という感じです。 finalizerを動かした後に、もしロックされたMutexがあればもう一度rb_mutex_unlock_all()すれば良いかと思いましたが、rb_mutex_unlock_all()はthread.cからしか呼べないのでした。 ---------------------------------------- Bug #4988: ObjectSpace.#define_finalizer内でMutexをロックして解放しないまま抜けるとabortする http://redmine.ruby-lang.org/issues/4988 Author: Masaki Matsushita Status: Open Priority: Normal Assignee: Category: Target version: ruby -v: ruby 1.9.3dev (2011-07-07 trunk 32437) [x86_64-linux] =begin 次のコードを実行すると、 ObjectSpace.define_finalizer("") do Mutex.new.lock end 以下のようにabortします。 [BUG] thread_free: keeping_mutexes must be NULL (0x1fa0510:0x21f8ac0) ruby 1.9.3dev (2011-07-07 trunk 32437) [x86_64-linux] -- Control frame information ----------------------------------------------- -- C level backtrace information ------------------------------------------- ../ruby_trunk/bin/ruby() [0x529687] vm_dump.c:796 ../ruby_trunk/bin/ruby() [0x576768] error.c:258 ../ruby_trunk/bin/ruby(rb_bug+0xa2) [0x577bc2] error.c:270 ../ruby_trunk/bin/ruby(ruby_vm_destruct+0x17f) [0x52741f] vm.c:1744 ../ruby_trunk/bin/ruby(ruby_cleanup+0x283) [0x4174c3] eval.c:184 ../ruby_trunk/bin/ruby(ruby_run_node+0x3d) [0x4176cd] eval.c:241 ../ruby_trunk/bin/ruby() [0x414849] main.c:38 /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xff) [0x7f7785469eff] ../ruby_trunk/bin/ruby() [0x414739] また、ruby 1.9.2p180ではabortせず、SEGVしました。 インタプリタの終了処理の際、eval.cのruby_cleanup()ではthread.cのrb_thread_terminate_all()が呼ばれ、そこからさらにrb_mutex_unlock_all()が呼ばれて全てのMutexが解放された後に ruby_finalize_1()が呼ばれてrb_gc_call_finalizer_at_exit()でfinalizerが実行されますが、finalizer内で新たにMutexをロックして解放しないまま抜けてしまうと、 その後呼ばれるruby_vm_destruct()内のthread_free()で落ちます。 rb_gc_call_finalizer_at_exit()をrb_thread_terminate_all()よりも先に呼ぶようにしたところabortしなくなったので、パッチを添付します。 =end -- http://redmine.ruby-lang.org