From 9873af0b1a343dff6d1a8af4c813aa2c9ecc47d5 Mon Sep 17 00:00:00 2001 From: Koichi Sasada Date: Thu, 9 Dec 2021 03:50:17 +0900 Subject: `TracePoint.allow_reentry` In general, while TracePoint callback is running, other registerred callbacks are not called to avoid confusion by reentrace. This method allow the reentrace. This method should be used carefully, otherwize the callback can be easily called infinitely. [Feature #15912] Co-authored-by: Jean Boussier --- vm_trace.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'vm_trace.c') diff --git a/vm_trace.c b/vm_trace.c index 3a0f7a7aad..f1c0bb2598 100644 --- a/vm_trace.c +++ b/vm_trace.c @@ -1517,6 +1517,25 @@ tracepoint_stat_s(rb_execution_context_t *ec, VALUE self) return stat; } +static VALUE +disallow_reentry(VALUE val) +{ + rb_trace_arg_t *arg = (rb_trace_arg_t *)val; + rb_execution_context_t *ec = GET_EC(); + if (ec->trace_arg != NULL) rb_bug("should be NULL, but %p", (void *)ec->trace_arg); + ec->trace_arg = arg; + return Qnil; +} + +static VALUE +tracepoint_allow_reentry(rb_execution_context_t *ec, VALUE self) +{ + const rb_trace_arg_t *arg = ec->trace_arg; + if (arg == NULL) rb_raise(rb_eRuntimeError, "No need to allow reentrance."); + ec->trace_arg = NULL; + return rb_ensure(rb_yield, Qnil, disallow_reentry, (VALUE)arg); +} + #include "trace_point.rbinc" /* This function is called from inits.c */ -- cgit v1.2.3