commit 890d31846b8f28be563534002e92b564b5a09bb6 Author: KOSAKI Motohiro Date: Wed Nov 28 19:50:31 2012 -0500 terminate_all deadlock check diff --git a/eval.c b/eval.c index 35202ce..0b8f4a4 100644 --- a/eval.c +++ b/eval.c @@ -185,8 +185,13 @@ ruby_cleanup(volatile int ex) if ((state = EXEC_TAG()) == 0) { SAVE_ROOT_JMPBUF(th, rb_thread_terminate_all()); } - else if (ex == 0) { - ex = state; + else { + if (state == TAG_FATAL) { + ex = state; + errs[1] = th->errinfo; + } else if (ex == 0) { + ex = state; + } } th->errinfo = errs[1]; ex = error_handle(ex); diff --git a/thread.c b/thread.c index 56891bc..00a9a90 100644 --- a/thread.c +++ b/thread.c @@ -389,12 +389,17 @@ rb_thread_terminate_all(void) TH_PUSH_TAG(th); if ((state = TH_EXEC_TAG()) == 0) { + GET_VM()->sleeper++; native_sleep(th, 0); + GET_VM()->sleeper--; RUBY_VM_CHECK_INTS_BLOCKING(th); } TH_POP_TAG(); - if (state) { + if (state == TAG_FATAL) { + JUMP_TAG(state); + } + else if (state) { goto retry; } } @@ -1789,7 +1794,10 @@ rb_threadptr_execute_interrupts(rb_thread_t *th, int blocking_timing) if (th->status == THREAD_STOPPED || th->status == THREAD_STOPPED_FOREVER) th->status = THREAD_RUNNABLE; - rb_exc_raise(err); + if (rb_obj_is_kind_of(err, rb_eFatal)) + rb_exc_fatal(err); + else + rb_exc_raise(err); } } @@ -1833,8 +1841,12 @@ static VALUE rb_threadptr_raise(rb_thread_t *th, int argc, VALUE *argv) { VALUE exc; + int fatal = 0; - if (rb_threadptr_dead(th)) { + if (argc >= 1 && argv[0] == rb_eFatal) + fatal = 1; + + if (!fatal && rb_threadptr_dead(th)) { return Qnil; } @@ -4869,7 +4881,8 @@ check_deadlock_i(st_data_t key, st_data_t val, int *found) rb_thread_t *th; GetThreadPtr(thval, th); - if (th->status != THREAD_STOPPED_FOREVER || RUBY_VM_INTERRUPTED(th)) { + if ((th->status & (THREAD_RUNNABLE|THREAD_STOPPED)) || + RUBY_VM_INTERRUPTED(th)) { *found = 1; } else if (th->locking_mutex) { diff --git a/vm_core.h b/vm_core.h index b29df8e..a31a54d 100644 --- a/vm_core.h +++ b/vm_core.h @@ -425,10 +425,10 @@ extern const rb_data_type_t ruby_threadptr_data_type; TypedData_Get_Struct((obj), rb_thread_t, &ruby_threadptr_data_type, (ptr)) enum rb_thread_status { - THREAD_RUNNABLE, - THREAD_STOPPED, - THREAD_STOPPED_FOREVER, - THREAD_KILLED + THREAD_RUNNABLE = 0x1, + THREAD_STOPPED = 0x2, + THREAD_STOPPED_FOREVER = 0x4, + THREAD_KILLED = 0x8, }; typedef RUBY_JMP_BUF rb_jmpbuf_t;