summaryrefslogtreecommitdiff
path: root/thread.c
diff options
context:
space:
mode:
authornobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2013-10-10 18:36:54 +0000
committernobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2013-10-10 18:36:54 +0000
commit53861b8acd18cc5241d044f6246568cbac6a31cf (patch)
tree19a9e2139e2e72178b42f7b2887be8d216210ebc /thread.c
parentabd6dc8c10dc8dc8f19898cef507be2e13ed1d0e (diff)
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.c38
1 files changed, 21 insertions, 17 deletions
diff --git a/thread.c b/thread.c
index 4789dfa..11ec96e 100644
--- a/thread.c
+++ b/thread.c
@@ -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