From 33ab98f9e690b6505804a10b08e66fb366f9838b Mon Sep 17 00:00:00 2001 From: ko1 Date: Fri, 11 Oct 2013 09:13:18 +0000 Subject: [PATCH] * ext/objspace/gc_hook.c: prohibit reentrant. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@43253 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 4 ++++ ext/objspace/gc_hook.c | 33 ++++++++++++++++++++++++++++----- 2 files changed, 32 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index 0809274fe0..009fe27845 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +Fri Oct 11 18:12:47 2013 Koichi Sasada + + * ext/objspace/gc_hook.c: prohibit reentrant. + Fri Oct 11 18:11:34 2013 Koichi Sasada * vm_trace.c (rb_postponed_job_flush): fix bit operation. diff --git a/ext/objspace/gc_hook.c b/ext/objspace/gc_hook.c index 7796eec61a..cf3dc0cc9d 100644 --- a/ext/objspace/gc_hook.c +++ b/ext/objspace/gc_hook.c @@ -16,19 +16,40 @@ #include "ruby/ruby.h" #include "ruby/debug.h" +static int invoking; /* TODO: should not be global variable */ + +static VALUE +invoke_proc_ensure(void *dmy) +{ + invoking = 0; + return Qnil; +} + +static VALUE +invoke_proc_begin(VALUE proc) +{ + return rb_proc_call(proc, rb_ary_new()); +} + static void invoke_proc(void *data) { VALUE proc = (VALUE)data; - rb_proc_call(proc, rb_ary_new()); + invoking += 1; + rb_ensure(invoke_proc_begin, proc, invoke_proc_ensure, 0); } static void gc_start_end_i(VALUE tpval, void *data) { - rb_trace_arg_t *tparg = rb_tracearg_from_tracepoint(tpval); - if (0) fprintf(stderr, "trace: %s\n", rb_tracearg_event_flag(tparg) == RUBY_INTERNAL_EVENT_GC_START ? "gc_start" : "gc_end"); - rb_postponed_job_register(0, invoke_proc, data); + if (0) { + rb_trace_arg_t *tparg = rb_tracearg_from_tracepoint(tpval); + fprintf(stderr, "trace: %s\n", rb_tracearg_event_flag(tparg) == RUBY_INTERNAL_EVENT_GC_START ? "gc_start" : "gc_end"); + } + + if (invoking == 0) { + rb_postponed_job_register(0, invoke_proc, data); + } } static VALUE @@ -38,7 +59,9 @@ set_gc_hook(VALUE rb_mObjSpace, VALUE proc, rb_event_flag_t event, const char *t ID tp_key = rb_intern(tp_str); ID proc_key = rb_intern(proc_str); - if (RTEST(tpval = rb_ivar_get(rb_mObjSpace, tp_key))) { + /* disable previous keys */ + if (rb_ivar_defined(rb_mObjSpace, tp_key) != 0 && + RTEST(tpval = rb_ivar_get(rb_mObjSpace, tp_key))) { rb_tracepoint_disable(tpval); rb_ivar_set(rb_mObjSpace, tp_key, Qnil); rb_ivar_set(rb_mObjSpace, proc_key, Qnil);