Hi,

# Moving to ruby-core.

At Wed, 15 May 2002 22:22:57 +0900,
ts wrote:
> J> However this does not solve problem in the script above.
> J> Problem is probably in thread switching somewhere.
> 
>  The problem, I think, is that when rb_thread_trap_eval() is executed
>  the main_thread lost its status and wait_for (call to
>  rb_thread_ready(main_thread)).
>  At the end of the code executed by #trap, the main_thread has the status
>  THREAD_RUNNABLE and wait_for = 0, this is why ruby enter in the accept(2)
> 
>  Perhaps a solution is to save these values (in th_status and th_wait_for
>  before the call to rb_thread_ready(main_thread)) and restore it when ruby
>  execute thread_switch(RESTORE_TRAP) 

Sure.  But I wonder if other values should be preserved.

Adding to it, rb_thread_schedule() should not return while the
current thread is stopped.


Index: eval.c =================================================================== RCS file: /cvs/ruby/src/ruby/eval.c,v retrieving revision 1.293 diff -u -2 -p -r1.293 eval.c --- eval.c 2002/05/14 06:22:25 1.293 +++ eval.c 2002/05/16 04:40:30 @@ -1426,26 +1426,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; @@ -7258,4 +7236,79 @@ struct thread { #define END_FOREACH(x) END_FOREACH_FROM(curr_thread,x) +struct thread_status_t { + char *file; + int line; + + 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)->file = (src)->file, \ + (dst)->line = (src)->line, \ + \ + (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 \ +) + +static void rb_thread_ready _((rb_thread_t)); + +static VALUE +rb_trap_eval(cmd, sig) + VALUE cmd; + int sig; +{ + int state; + VALUE val; /* OK */ + 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); + } + return val; +} + static const char * thread_status_name(status) @@ -7716,5 +7769,5 @@ rb_thread_schedule() rb_thread_t th; rb_thread_t curr; - int found = 0; + int found; fd_set readfds; @@ -7724,6 +7777,6 @@ rb_thread_schedule() double delay, now; /* OK */ int n, max; - int need_select = 0; - int select_timeout = 0; + int need_select; + int select_timeout; rb_thread_pending = 0; @@ -7732,4 +7785,8 @@ rb_thread_schedule() return; + reschedule: + found = 0; + need_select = 0; + select_timeout = 0; next = 0; curr = curr_thread; /* starting thread */ @@ -7919,4 +7976,5 @@ rb_thread_schedule() if (curr == curr_thread) { if (THREAD_SAVE_CONTEXT(curr)) { + if (curr_thread->status == THREAD_STOPPED) goto reschedule; return; } @@ -8862,5 +8920,4 @@ rb_thread_trap_eval(cmd, sig) } } - rb_thread_ready(main_thread); th_cmd = cmd; th_sig = sig;
-- Nobu Nakada