なかだです。

At Tue, 30 Nov 2004 23:59:59 +0900,
Tanaka Akira wrote in [ruby-dev:25003]:
> 次のようにすると core を吐きます。
> 
> % ./ruby -ve '
> r, w = IO.pipe
> w.sync = false
> w << "a" * 4096
> w.flush
> pid = fork {
>   w.close
>   sleep 0.1
>   Process.kill("USR1", Process.ppid)
>   r.sysread(4096)
>   sleep 0.1
>   r.sysread(1000)
> }
> r.close
> w << "b"
> trap("USR1") { callcc {|k| $k = k } }
> w.flush
> w.close
> $k.call
> '
> ruby 1.9.0 (2004-11-30) [i686-linux]
> -e:17: [BUG] Segmentation fault
> ruby 1.9.0 (2004-11-30) [i686-linux]

IO#flushの問題というよりは、trapを跨いだContinuationの呼び出し
が問題だと思うんですが、あってるでしょうか。

かなり苦し紛れですが。


Index: eval.c =================================================================== RCS file: /cvs/ruby/src/ruby/eval.c,v retrieving revision 1.737 diff -U2 -p -d -r1.737 eval.c --- eval.c 30 Nov 2004 09:33:50 -0000 1.737 +++ eval.c 30 Nov 2004 16:12:23 -0000 @@ -9681,5 +9681,5 @@ rb_trap_eval(cmd, sig, safe) THREAD_COPY_STATUS(curr_thread, &save); rb_thread_ready(curr_thread); - PUSH_TAG(PROT_NONE); + PUSH_TAG(PROT_TOP); PUSH_ITER(ITER_NOT); if ((state = EXEC_TAG()) == 0) { @@ -11917,4 +11917,8 @@ rb_thread_trap_eval(cmd, sig, safe) { rb_thread_critical = 0; + if (curr_thread == main_thread) { + rb_trap_eval(cmd, sig, safe); + return; + } if (!rb_thread_dead(curr_thread)) { if (THREAD_SAVE_CONTEXT(curr_thread)) { @@ -12261,5 +12265,5 @@ rb_callcc(self) rb_thread_t th; volatile rb_thread_t th_save; - struct tag *tag; + struct tag *tag, *top = 0; struct RVarmap *vars; @@ -12270,6 +12274,8 @@ rb_callcc(self) for (tag=prot_tag; tag; tag=tag->prev) { scope_dup(tag->scope); + if (!top && tag->tag == PROT_TOP) top = tag; } th->thread = curr_thread->thread; + th->join = (void *)top; for (vars = ruby_dyna_vars; vars; vars = vars->next) { @@ -12309,8 +12315,18 @@ rb_cont_call(argc, argv, cont) { rb_thread_t th = rb_thread_check(cont); + struct tag *tag, *top = 0; if (th->thread != curr_thread->thread) { rb_raise(rb_eRuntimeError, "continuation called across threads"); } + for (tag=prot_tag; tag; tag=tag->prev) { + if (tag->tag == PROT_TOP) { + top = tag; + break; + } + } + if ((void *)th->join != (void *)top) { + rb_raise(rb_eRuntimeError, "continuation called across trap"); + } switch (argc) { case 0:
-- --- 僕の前にBugはない。 --- 僕の後ろにBugはできる。 中田 伸悦