From fa4514e4fedc1e1390200e3901e2add22a4a27b4 Mon Sep 17 00:00:00 2001 From: ko1 Date: Thu, 30 Jun 2011 22:29:34 +0000 Subject: [PATCH] * thread.c (rb_threadptr_check_signal): only wake up main thread. * thread.c (rb_threadptr_execute_interrupts_common): check signal deliverly if it is main thread. fixes [ruby-dev:44005] [Ruby 1.9 - Bug #4950] * bootstraptest/test_fork.rb: add a test for above. * signal.c (rb_get_next_signal): skip if signal_buff is empty. (check signal_buff.size first) * vm_core.h: remove unused variable rb_thread_t::exec_signal. * thread.c (rb_thread_check_trap_pending): check rb_signal_buff_size() because rb_thread_t::exec_signal is no longer available. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@32345 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 19 +++++++++++++++++++ bootstraptest/test_fork.rb | 20 ++++++++++++++++++++ signal.c | 20 +++++++++++--------- thread.c | 20 ++++++++------------ vm_core.h | 1 - 5 files changed, 58 insertions(+), 22 deletions(-) diff --git a/ChangeLog b/ChangeLog index 5c5e270b09..acd13d9ab7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,22 @@ +Fri Jul 1 06:41:36 2011 Koichi Sasada + + * thread.c (rb_threadptr_check_signal): only wake up main thread. + + * thread.c (rb_threadptr_execute_interrupts_common): check signal + deliverly if it is main thread. + fixes [ruby-dev:44005] [Ruby 1.9 - Bug #4950] + + * bootstraptest/test_fork.rb: add a test for above. + + * signal.c (rb_get_next_signal): skip if signal_buff is empty. + (check signal_buff.size first) + + * vm_core.h: remove unused variable rb_thread_t::exec_signal. + + * thread.c (rb_thread_check_trap_pending): check + rb_signal_buff_size() because rb_thread_t::exec_signal + is no longer available. + Fri Jul 1 03:28:25 2011 Yukihiro Matsumoto * class.c (Init_class_hierarchy): should name BasicObject diff --git a/bootstraptest/test_fork.rb b/bootstraptest/test_fork.rb index d9e92c7a6b..384294727f 100644 --- a/bootstraptest/test_fork.rb +++ b/bootstraptest/test_fork.rb @@ -47,3 +47,23 @@ assert_equal 'ok', %q{ :ok end }, '[ruby-core:28924]' + +assert_equal '[1, 2]', %q{ + a = [] + trap(:INT) { a.push(1) } + trap(:TERM) { a.push(2) } + pid = $$ + begin + fork do + sleep 0.5 + Process.kill(:INT, pid) + Process.kill(:TERM, pid) + end + + sleep 1 + a.sort + rescue NotImplementedError + [1, 2] + end +}, '[ruby-dev:44005] [Ruby 1.9 - Bug #4950]' + diff --git a/signal.c b/signal.c index 6c4028e789..f02e3db15c 100644 --- a/signal.c +++ b/signal.c @@ -554,16 +554,18 @@ rb_get_next_signal(void) { int i, sig = 0; - for (i=1; i 0) { - rb_disable_interrupt(); - { - ATOMIC_DEC(signal_buff.cnt[i]); - ATOMIC_DEC(signal_buff.size); + if (signal_buff.size != 0) { + for (i=1; i 0) { + rb_disable_interrupt(); + { + ATOMIC_DEC(signal_buff.cnt[i]); + ATOMIC_DEC(signal_buff.size); + } + rb_enable_interrupt(); + sig = i; + break; } - rb_enable_interrupt(); - sig = i; - break; } } return sig; diff --git a/thread.c b/thread.c index ab547a1d0a..9e869069fc 100644 --- a/thread.c +++ b/thread.c @@ -981,7 +981,7 @@ rb_thread_check_ints(void) int rb_thread_check_trap_pending(void) { - return GET_THREAD()->exec_signal != 0; + return rb_signal_buff_size() != 0; } /* This function can be called in blocking region. */ @@ -1269,14 +1269,15 @@ rb_threadptr_execute_interrupts_common(rb_thread_t *th) enum rb_thread_status status = th->status; int timer_interrupt = interrupt & 0x01; int finalizer_interrupt = interrupt & 0x04; + int sig; th->status = THREAD_RUNNABLE; /* signal handling */ - if (th->exec_signal) { - int sig = th->exec_signal; - th->exec_signal = 0; - rb_signal_exec(th, sig); + if (th == th->vm->main_thread) { + while ((sig = rb_get_next_signal()) != 0) { + rb_signal_exec(th, sig); + } } /* exception from another thread */ @@ -2934,14 +2935,9 @@ rb_gc_save_machine_context(rb_thread_t *th) void rb_threadptr_check_signal(rb_thread_t *mth) { - int sig; - /* mth must be main_thread */ - - if (!mth->exec_signal && (sig = rb_get_next_signal()) > 0) { - thread_debug("main_thread: %s, sig: %d\n", - thread_status_name(mth->status), sig); - mth->exec_signal = sig; + if (rb_signal_buff_size() > 0) { + /* wakeup main thread */ rb_threadptr_interrupt(mth); } } diff --git a/vm_core.h b/vm_core.h index 720e9c33fc..27961287b0 100644 --- a/vm_core.h +++ b/vm_core.h @@ -428,7 +428,6 @@ typedef struct rb_thread_struct { VALUE errinfo; VALUE thrown_errinfo; - int exec_signal; rb_atomic_t interrupt_flag; rb_thread_lock_t interrupt_lock;