diff options
author | nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2013-10-10 18:36:54 +0000 |
---|---|---|
committer | nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2013-10-10 18:36:54 +0000 |
commit | 53861b8acd18cc5241d044f6246568cbac6a31cf (patch) | |
tree | 19a9e2139e2e72178b42f7b2887be8d216210ebc /thread.c | |
parent | abd6dc8c10dc8dc8f19898cef507be2e13ed1d0e (diff) | |
download | ruby-53861b8acd18cc5241d044f6246568cbac6a31cf.tar.gz |
vm_trace.c: fix infinite hook
* thread.c (rb_threadptr_execute_interrupts): flush postponed job only
once at last.
* vm_trace.c (rb_postponed_job_flush): defer calling postponed jobs
registered while flushing to get rid of infinite reentrance of
ObjectSpace.after_gc_start_hook. [ruby-dev:47400] [Bug #8492]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@43245 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'thread.c')
-rw-r--r-- | thread.c | 38 |
1 files changed, 21 insertions, 17 deletions
@@ -1924,29 +1924,33 @@ rb_threadptr_to_kill(rb_thread_t *th) TH_JUMP_TAG(th, TAG_FATAL); } +static inline rb_atomic_t +threadptr_get_interrupts(rb_thread_t *th) +{ + rb_atomic_t interrupt; + rb_atomic_t old; + + do { + interrupt = th->interrupt_flag; + old = ATOMIC_CAS(th->interrupt_flag, interrupt, interrupt & th->interrupt_mask); + } while (old != interrupt); + return interrupt & (rb_atomic_t)~th->interrupt_mask; +} + void rb_threadptr_execute_interrupts(rb_thread_t *th, int blocking_timing) { + rb_atomic_t interrupt; + int postponed_job_interrupt = 0; + if (th->raised_flag) return; - while (1) { - rb_atomic_t interrupt; - rb_atomic_t old; + while ((interrupt = threadptr_get_interrupts(th)) != 0) { int sig; int timer_interrupt; int pending_interrupt; - int postponed_job_interrupt; int trap_interrupt; - do { - interrupt = th->interrupt_flag; - old = ATOMIC_CAS(th->interrupt_flag, interrupt, interrupt & th->interrupt_mask); - } while (old != interrupt); - - interrupt &= (rb_atomic_t)~th->interrupt_mask; - if (!interrupt) - return; - timer_interrupt = interrupt & TIMER_INTERRUPT_MASK; pending_interrupt = interrupt & PENDING_INTERRUPT_MASK; postponed_job_interrupt = interrupt & POSTPONED_JOB_INTERRUPT_MASK; @@ -1984,10 +1988,6 @@ rb_threadptr_execute_interrupts(rb_thread_t *th, int blocking_timing) } } - if (postponed_job_interrupt) { - rb_postponed_job_flush(th->vm); - } - if (timer_interrupt) { unsigned long limits_us = TIME_QUANTUM_USEC; @@ -2004,6 +2004,10 @@ rb_threadptr_execute_interrupts(rb_thread_t *th, int blocking_timing) rb_thread_schedule_limits(limits_us); } } + + if (postponed_job_interrupt) { + rb_postponed_job_flush(th->vm); + } } void |