diff options
author | Koichi Sasada <[email protected]> | 2021-12-09 03:50:17 +0900 |
---|---|---|
committer | Koichi Sasada <[email protected]> | 2021-12-10 00:56:25 +0900 |
commit | 9873af0b1a343dff6d1a8af4c813aa2c9ecc47d5 (patch) | |
tree | c400e0a544ff9150f28413fd9f27c6bc2a5de276 /vm_trace.c | |
parent | 88c804a6e720d85afbd6714113a85e6beb48c296 (diff) |
`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 <[email protected]>
Notes
Notes:
Merged: https://github.com/ruby/ruby/pull/5231
Diffstat (limited to 'vm_trace.c')
-rw-r--r-- | vm_trace.c | 19 |
1 files changed, 19 insertions, 0 deletions
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 */ |