From: nobu.nakada@... Date: 2002-09-11T17:19:12+09:00 Subject: [ruby-dev:18266] thread failure after trap なかだです。 [ruby-talk:40337]と[ruby-core:00019]の、trapでthreadがブロック してしまうという件ですが、どうすべきでしょうか。 とりあえず、[ruby-core:00023]+[ruby-core:00026]をCVS HEAD用にし たパッチです。 * eval.c (rb_trap_eval): preserve thread status and so on. Index: eval.c =================================================================== RCS file: /cvs/ruby/src/ruby/eval.c,v retrieving revision 1.325 diff -u -2 -p -r1.325 eval.c --- eval.c 10 Sep 2002 15:44:36 -0000 1.325 +++ eval.c 10 Sep 2002 15:48:36 -0000 @@ -1468,26 +1468,4 @@ rb_eval_cmd(cmd, arg, tcheck) static VALUE -rb_trap_eval(cmd, sig) - VALUE cmd; - int sig; -{ - int state; - VALUE val; /* OK */ - - PUSH_TAG(PROT_NONE); - PUSH_ITER(ITER_NOT); - if ((state = EXEC_TAG()) == 0) { - val = rb_eval_cmd(cmd, rb_ary_new3(1, INT2FIX(sig)), 0); - } - POP_ITER(); - POP_TAG(); - if (state) { - rb_trap_immediate = 0; - JUMP_TAG(state); - } - return val; -} - -static VALUE superclass(self, node) VALUE self; @@ -7363,4 +7341,83 @@ struct thread { #define END_FOREACH(x) END_FOREACH_FROM(curr_thread,x) +struct thread_status_t { + NODE *node; + + int tracing; + VALUE errinfo; + VALUE last_status; + VALUE last_line; + VALUE last_match; + + int safe; + + enum thread_status status; + int wait_for; + int fd; + fd_set readfds; + fd_set writefds; + fd_set exceptfds; + int select_value; + double delay; + rb_thread_t join; +}; + +#define THREAD_COPY_STATUS(src, dst) (void)( \ + (dst)->node = (src)->node, \ + \ + (dst)->tracing = (src)->tracing, \ + (dst)->errinfo = (src)->errinfo, \ + (dst)->last_status = (src)->last_status, \ + (dst)->last_line = (src)->last_line, \ + (dst)->last_match = (src)->last_match, \ + \ + (dst)->safe = (src)->safe, \ + \ + (dst)->status = (src)->status, \ + (dst)->wait_for = (src)->wait_for, \ + (dst)->fd = (src)->fd, \ + (dst)->readfds = (src)->readfds, \ + (dst)->writefds = (src)->writefds, \ + (dst)->exceptfds = (src)->exceptfds, \ + (dst)->select_value = (src)->select_value, \ + (dst)->delay = (src)->delay, \ + (dst)->join = (src)->join, \ + 0) + +static void rb_thread_ready _((rb_thread_t)); + +static VALUE +rb_trap_eval(cmd, sig) + VALUE cmd; + int sig; +{ + int state; + VALUE val; /* OK */ + volatile struct thread_status_t save; + + THREAD_COPY_STATUS(curr_thread, &save); + rb_thread_ready(curr_thread); + PUSH_TAG(PROT_NONE); + PUSH_ITER(ITER_NOT); + if ((state = EXEC_TAG()) == 0) { + val = rb_eval_cmd(cmd, rb_ary_new3(1, INT2FIX(sig)), 0); + } + POP_ITER(); + POP_TAG(); + THREAD_COPY_STATUS(&save, curr_thread); + + if (state) { + rb_trap_immediate = 0; + JUMP_TAG(state); + } + + if (curr_thread->status == THREAD_STOPPED) { + rb_thread_schedule(); + } + errno = EINTR; + + return val; +} + static const char * thread_status_name(status) @@ -7599,5 +7656,4 @@ thread_switch(n) case RESTORE_TRAP: rb_trap_eval(th_cmd, th_sig); - errno = EINTR; break; case RESTORE_RAISE: @@ -8961,5 +9017,4 @@ rb_thread_trap_eval(cmd, sig) } } - rb_thread_ready(main_thread); th_cmd = cmd; th_sig = sig; -- --- 僕の前にBugはない。 --- 僕の後ろにBugはできる。 中田 伸悦