From c746b6fa42b1e68fb7284aa616d5ba7aef404dee Mon Sep 17 00:00:00 2001 From: naruse Date: Thu, 26 Apr 2012 23:19:11 +0000 Subject: * thread.c (rb_threadptr_execute_interrupts_common): handle timer_interrupt only on the first loop for the case to avoid the infinite loop like following case: * there is 2 Ruby threads (3 pthreads) (1) main thread is waiting at gvl_yield:112 (native_cond_wait) (2) sub thread works (3) sub thread waits at gvl_yield:133 (native_mutex_unlock) (4) main thread works (5) main thread goes to gvl_acquire_common (6) main thread call rb_wakeup_timer_thread (7) timer thread set timer interrupt to the main thread (8) main thread works (9) main thread waits at gvl_acquire_common:64 (native_cond_wait) (10) sub tread works (11) set sub thread as the current thread (12) run Ruby thread (13) ...100ms (14) sub thread goes to rb_threadptr_execute_interrupts_common (15) sub thread call rb_thread_schedule_limits (16) sub thread call gvl_release_common (17) sub threads waits at gvl_yield:121 (native_cond_wait) (18) main threads works (19) main thread back to gvl_yield (20) set main thread as the current thread (21) main thread call gvl_yield (22) main thread waits at gvl_yield:112 (native_cond_wait) As described above, the main thread can't escape from rb_threadptr_execute_interrupts_common. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@35480 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 31 +++++++++++++++++++++++++++++++ thread.c | 6 ++++++ 2 files changed, 37 insertions(+) diff --git a/ChangeLog b/ChangeLog index 2dd3a27542..47cbe0ef5a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,34 @@ +Fri Apr 27 01:45:05 2012 NARUSE, Yui + + * thread.c (rb_threadptr_execute_interrupts_common): + handle timer_interrupt only on the first loop for the case to avoid + the infinite loop like following case: + * there is 2 Ruby threads (3 pthreads) + (1) main thread is waiting at gvl_yield:112 (native_cond_wait) + (2) sub thread works + (3) sub thread waits at gvl_yield:133 (native_mutex_unlock) + (4) main thread works + (5) main thread goes to gvl_acquire_common + (6) main thread call rb_wakeup_timer_thread + (7) timer thread set timer interrupt to the main thread + (8) main thread works + (9) main thread waits at gvl_acquire_common:64 (native_cond_wait) + (10) sub tread works + (11) set sub thread as the current thread + (12) run Ruby thread + (13) ...100ms + (14) sub thread goes to rb_threadptr_execute_interrupts_common + (15) sub thread call rb_thread_schedule_limits + (16) sub thread call gvl_release_common + (17) sub threads waits at gvl_yield:121 (native_cond_wait) + (18) main threads works + (19) main thread back to gvl_yield + (20) set main thread as the current thread + (21) main thread call gvl_yield + (22) main thread waits at gvl_yield:112 (native_cond_wait) + As described above, the main thread can't escape from + rb_threadptr_execute_interrupts_common. + Fri Apr 27 07:15:07 2012 Tanaka Akira * ext/socket/socket.c (sock_s_pack_sockaddr_un): support the longest diff --git a/thread.c b/thread.c index 7383a886f6..a63c9528de 100644 --- a/thread.c +++ b/thread.c @@ -1273,6 +1273,7 @@ static void rb_threadptr_execute_interrupts_common(rb_thread_t *th) { rb_atomic_t interrupt; + int first_p = TRUE; if (th->raised_flag) return; @@ -1282,6 +1283,11 @@ rb_threadptr_execute_interrupts_common(rb_thread_t *th) int finalizer_interrupt = interrupt & 0x04; int sig; + if (first_p) + first_p = FALSE; + else if (interrupt == 0x01) + break; + th->status = THREAD_RUNNABLE; /* signal handling */ -- cgit v1.2.3