Index: cont.c =================================================================== --- cont.c (revision 26315) +++ cont.c (working copy) @@ -589,6 +589,7 @@ case 0: return Qnil; case 1: + case -2: return argv[0]; default: return rb_ary_new4(argc, argv); @@ -919,6 +920,7 @@ /* restored */ GetFiberPtr(th->fiber, fib); if (fib->cont.argc == -1) rb_exc_raise(fib->cont.value); + else if (fib->cont.argc == -2) rb_throw_obj(fib->cont.value, Qnil); return fib->cont.value; } else { @@ -1013,6 +1015,34 @@ return fib->status != TERMINATED ? Qtrue : Qfalse; } +static VALUE +terminate_all_i(VALUE tag, VALUE fibval) +{ + if (rb_fiber_alive_p(fibval)) { + return fiber_switch(fibval, -2, &tag, 0); + } +} + +void +rb_fiber_terminate_all(rb_thread_t *th) +{ + VALUE fibval, tag = rb_newobj(); + rb_fiber_t *fib, *root_fib; + rb_thread_t *_th = GET_THREAD(); + + rb_thread_set_current(th); + fibval = th->root_fiber; + if (!RTEST(fibval)) return; + GetFiberPtr(fibval, root_fib); + + fib = root_fib->prev_fiber; + while (fib != root_fib) { + rb_catch_obj(tag, terminate_all_i, fib->cont.self); + fib = fib->prev_fiber; + } + rb_thread_set_current(_th); +} + /* * call-seq: * fiber.resume(args, ...) -> obj Index: thread.c =================================================================== --- thread.c (revision 26315) +++ thread.c (working copy) @@ -324,6 +324,7 @@ static void rb_mutex_unlock_all(mutex_t *mutex, rb_thread_t *th); static void rb_mutex_abandon_all(mutex_t *mutexes); +void rb_fiber_terminate_all(rb_thread_t *th); void rb_thread_terminate_all(void) @@ -345,6 +346,7 @@ thread_debug("rb_thread_terminate_all (main thread: %p)\n", (void *)th); st_foreach(vm->living_threads, terminate_i, (st_data_t)th); + rb_fiber_terminate_all(th); while (!rb_thread_alone()) { PUSH_TAG(); @@ -1254,6 +1256,7 @@ thread_debug("rb_thread_execute_interrupts: %ld\n", err); if (err == eKillSignal || err == eTerminateSignal) { + rb_fiber_terminate_all(th); th->errinfo = INT2FIX(TAG_FATAL); TH_JUMP_TAG(th, TAG_FATAL); }