Bug #935
closedchild process forked from child thread does not call ruby_cleanup
Description
=begin
[ruby-dev:37624] と完全に同一の内容ですが、redmine に登録し忘れたので
再送します。すみません。
遠藤です。
[ruby-dev:37447] を調べていて気がついたことですが、
子スレッドの中で fork したプロセスが ruby_cleanup をしません。
$ ./miniruby -e '
at_exit { p [:exit, $$] }
Thread.new { p [fork ? :parent : :child, $$] }
sleep 1
'
[:parent, 14543]
[:child, 14546]
[:exit, 14543]
1.8 であれば、上の例で [:exit, 14546] も表示されます。
at_exit が実行されない以外に、タイマースレッドだけ生き残ってプロセスが
終了しないとか、(おそらく) IO のファイナライザが呼び出されないとか、
いろいろと問題がある気がします。
末尾のパッチで、fork によってメインスレッドに昇格したスレッドの終了時に
ruby_cleanup(state) を呼ぶようになります。が、いろいろと副作用がありそうで
怖いです。
また、うちの環境 (Debian/lenny 32bit) では現在このパッチをあてなくても
make test-all で SEGV したり固まったりするので、ちゃんとテストできても
ないです。
どうしたもんでしょう。
Index: thread.c¶
--- thread.c (revision 21097)
+++ thread.c (working copy)
@@ -427,6 +427,8 @@
}
TH_POP_TAG();
-
if (main_th == th) ruby_cleanup(state);
-
/* locking_mutex must be Qfalse */
if (th->locking_mutex != Qfalse) {
rb_bug("thread_start_func_2: locking_mutex must not be set (%p:%"PRIxVALUE")",
@@ -440,7 +442,7 @@
}/* delete self from living_threads */
- st_delete_wrap(th->vm->living_threads, th->self);
-
if (main_th != th) st_delete_wrap(th->vm->living_threads, th->self);
/* wake up joinning threads */
join_th = th->join_list_head;
@@ -462,9 +464,6 @@
}
}
thread_cleanup_func(th);
-
if (th->vm->main_thread == th) {
-
rb_thread_stop_timer_thread();
-
}
native_mutex_unlock(&th->vm->global_vm_lock);return 0;
--
Yusuke ENDOH mame@tsg.ne.jp
=end