Child process forked from child thread does not call ruby_cleanup

e$B1sF#$G$9!#e(B

[ruby-dev:37447] e$B$rD4$Y$F$$$F5$$,$D$$$?$3$H$G$9$,!"e(B
e$B;R%9%l%C%I$NCf$Ge(B fork e$B$7$?%W%m%;%9$,e(B ruby_cleanup
e$B$r$7$^$;$s!#e(B

$ ./miniruby -e ’
at_exit { p [:exit, $$] }
Thread.new { p [fork ? :parent : :child, $$] }
sleep 1

[:parent, 14543]
[:child, 14546]
[:exit, 14543]

1.8 e$B$G$"$l$P!">e$NNc$Ge(B [:exit, 14546] e$B$bI=<($5$l$^$9!#e(B

at_exit
e$B$,<B9T$5$l$J$$0J30$K!"%?%$%^!<%9%l%C%I$@$1@8$-;D$C$F%W%m%;%9$,e(B
e$B=N;$7$J$$$H$+!"e(B(e$B$$=$i$/e(B) IO
e$B$N%U%!%$%J%i%$%6$,8F$S=P$5$l$J$$$H$+!“e(B
e$B$$$m$$$m$HLdBj$,$”$k5$$,$7$^$9!#e(B

e$BKvHx$N%Q%C%A$G!“e(Bfork
e$B$K$h$C$F%a%$%s%9%l%C%I$K>:3J$7$?%9%l%C%I$N=*N;;~$Ke(B
ruby_cleanup(state)
e$B$r8F$V$h$&$K$J$j$^$9!#$,!”$$$m$$$m$HI{:nMQ$,$"$j$=$&$Ge(B
e$BI]$$$G$9!#e(B

e$B$^$?!"$&$A$N4D6-e(B (Debian/lenny 32bit)
e$B$G$O8=:_$3$N%Q%C%A$r$"$F$J$/$F$be(B
make test-all e$B$Ge(B SEGV
e$B$7$?$j8G$^$C$?$j$9$k$N$G!"$A$c$s$H%F%9%H$G$-$F$be(B
e$B$J$$$G$9!#e(B

e$B$I$&$7$?$b$s$G$7$g$&!#e(B

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;