なかだです。 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はできる。 中田 伸悦