diff --git a/ChangeLog b/ChangeLog index cdacfb7ea2..cedb50a235 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +Mon Aug 13 05:03:53 2007 Koichi Sasada + + * thread.c (rb_thread_raise): check if target thread is + thrown by another thread or not. [ruby-dev:31371] + + * bootstraptest/test_thread.rb: add a test for above. + Mon Aug 13 04:35:30 2007 Koichi Sasada * compile.c (iseq_peephole_optimize): fix peephole optimization @@ -5,7 +12,6 @@ Mon Aug 13 04:35:30 2007 Koichi Sasada * bootstraptest/test_syntax.rb: add a test for above. - Mon Aug 13 04:02:29 2007 Koichi Sasada * vm_dump.c (debug_print_pre): fix to show control frame count. diff --git a/bootstraptest/test_thread.rb b/bootstraptest/test_thread.rb index 64d685fa19..40ccbad497 100644 --- a/bootstraptest/test_thread.rb +++ b/bootstraptest/test_thread.rb @@ -169,3 +169,17 @@ assert_equal %q{11}, %q{ Thread.current[:a] }.value + Thread.current[:a] } +assert_equal %q{1000}, %q{ +begin + 1000.times do |i| + begin + Thread.start(Thread.current) {|u| u.raise } + raise + rescue + ensure + end + end +rescue + 1000 +end +}, '[ruby-dev:31371]' diff --git a/thread.c b/thread.c index 7ff9439cf4..bae2fd7555 100644 --- a/thread.c +++ b/thread.c @@ -758,12 +758,17 @@ rb_thread_raise(int argc, VALUE *argv, rb_thread_t *th) { VALUE exc; + again: if (rb_thread_dead(th)) { return Qnil; } + if (th->thrown_errinfo != 0 || th->raised_flag) { + rb_thread_schedule(); + goto again; + } + exc = rb_make_exception(argc, argv); - /* TODO: need synchronization if run threads in parallel */ th->thrown_errinfo = exc; rb_thread_ready(th); return Qnil;