From a2950369bd8a5866092f6badf59b0811653a6092 Mon Sep 17 00:00:00 2001 From: Koichi Sasada Date: Sat, 19 Dec 2020 06:38:58 +0900 Subject: TracePoint.new(&block) should be ractor-local TracePoint should be ractor-local because the Proc can violate the Ractor-safe. --- bootstraptest/test_ractor.rb | 13 +++++++++++++ common.mk | 1 + ractor.c | 8 ++++++++ ractor_core.h | 2 ++ vm.c | 2 -- vm_core.h | 19 ++++++++++++------- vm_insnhelper.c | 2 +- vm_trace.c | 18 +++++++++++------- 8 files changed, 48 insertions(+), 17 deletions(-) diff --git a/bootstraptest/test_ractor.rb b/bootstraptest/test_ractor.rb index 797ad0a3ee..a853e91416 100644 --- a/bootstraptest/test_ractor.rb +++ b/bootstraptest/test_ractor.rb @@ -1199,6 +1199,19 @@ assert_equal '[false, false, true, true]', %q{ r } +# TracePoint with normal Proc should be Ractor local +assert_equal '[4, 8]', %q{ + rs = [] + TracePoint.new(:line){|tp| rs << tp.lineno if tp.path == __FILE__}.enable do + Ractor.new{ # line 4 + a = 1 + b = 2 + }.take + c = 3 # line 8 + end + rs +} + # Ractor deep copies frozen objects (ary) assert_equal '[true, false]', %q{ Ractor.new([[]].freeze) { |ary| diff --git a/common.mk b/common.mk index 2cfa952131..ca237d79b4 100644 --- a/common.mk +++ b/common.mk @@ -16316,6 +16316,7 @@ vm_trace.$(OBJEXT): {$(VPATH)}mjit.h vm_trace.$(OBJEXT): {$(VPATH)}node.h vm_trace.$(OBJEXT): {$(VPATH)}onigmo.h vm_trace.$(OBJEXT): {$(VPATH)}oniguruma.h +vm_trace.$(OBJEXT): {$(VPATH)}ractor.h vm_trace.$(OBJEXT): {$(VPATH)}ruby_assert.h vm_trace.$(OBJEXT): {$(VPATH)}ruby_atomic.h vm_trace.$(OBJEXT): {$(VPATH)}st.h diff --git a/ractor.c b/ractor.c index b8564199d5..f535e6e54d 100644 --- a/ractor.c +++ b/ractor.c @@ -197,6 +197,7 @@ ractor_mark(void *ptr) rb_gc_mark(r->r_stdin); rb_gc_mark(r->r_stdout); rb_gc_mark(r->r_stderr); + rb_hook_list_mark(&r->event_hooks); if (r->threads.cnt > 0) { rb_thread_t *th = 0; @@ -230,6 +231,7 @@ ractor_free(void *ptr) ractor_queue_free(&r->sync.incoming_queue); ractor_waiting_list_free(&r->sync.taking_ractors); ractor_local_storage_free(r); + rb_hook_list_free(&r->event_hooks); ruby_xfree(r); } @@ -2126,6 +2128,12 @@ rb_ractor_stderr_set(VALUE err) } } +rb_hook_list_t * +rb_ractor_hooks(rb_ractor_t *cr) +{ + return &cr->event_hooks; +} + /// traverse function // 2: stop search diff --git a/ractor_core.h b/ractor_core.h index daa652ebff..88b1126546 100644 --- a/ractor_core.h +++ b/ractor_core.h @@ -138,6 +138,8 @@ struct rb_ractor_struct { VALUE verbose; VALUE debug; + rb_hook_list_t event_hooks; + struct { struct RVALUE *freelist; struct heap_page *using_page; diff --git a/vm.c b/vm.c index 9ed358f73d..5fc0338334 100644 --- a/vm.c +++ b/vm.c @@ -2588,8 +2588,6 @@ rb_vm_mark(void *ptr) rb_mark_tbl(vm->loading_table); } - rb_hook_list_mark(&vm->global_hooks); - rb_gc_mark_values(RUBY_NSIG, vm->trap_list.cmd); rb_id_table_foreach_values(vm->negative_cme_table, vm_mark_negative_cme, NULL); diff --git a/vm_core.h b/vm_core.h index 304885b9ce..e86026ab50 100644 --- a/vm_core.h +++ b/vm_core.h @@ -619,9 +619,6 @@ typedef struct rb_vm_struct { VALUE cmd[RUBY_NSIG]; } trap_list; - /* hook */ - rb_hook_list_t global_hooks; - /* relation table of ensure - rollback for callcc */ struct st_table *ensure_rollback_table; @@ -1973,17 +1970,25 @@ rb_exec_event_hook_orig(rb_execution_context_t *ec, rb_hook_list_t *hooks, rb_ev rb_exec_event_hooks(&trace_arg, hooks, pop_p); } +rb_hook_list_t *rb_ractor_hooks(rb_ractor_t *cr);; + static inline rb_hook_list_t * -rb_vm_global_hooks(const rb_execution_context_t *ec) +rb_ec_ractor_hooks(const rb_execution_context_t *ec) { - return &rb_ec_vm_ptr(ec)->global_hooks; + rb_hook_list_t *hooks = rb_ractor_hooks(rb_ec_ractor_ptr(ec)); + if (LIKELY(hooks == NULL)) { + return NULL; + } + else { + return hooks; + } } #define EXEC_EVENT_HOOK(ec_, flag_, self_, id_, called_id_, klass_, data_) \ - EXEC_EVENT_HOOK_ORIG(ec_, rb_vm_global_hooks(ec_), flag_, self_, id_, called_id_, klass_, data_, 0) + EXEC_EVENT_HOOK_ORIG(ec_, rb_ec_ractor_hooks(ec_), flag_, self_, id_, called_id_, klass_, data_, 0) #define EXEC_EVENT_HOOK_AND_POP_FRAME(ec_, flag_, self_, id_, called_id_, klass_, data_) \ - EXEC_EVENT_HOOK_ORIG(ec_, rb_vm_global_hooks(ec_), flag_, self_, id_, called_id_, klass_, data_, 1) + EXEC_EVENT_HOOK_ORIG(ec_, rb_ec_ractor_hooks(ec_), flag_, self_, id_, called_id_, klass_, data_, 1) static inline void rb_exec_event_hook_script_compiled(rb_execution_context_t *ec, const rb_iseq_t *iseq, VALUE eval_script) diff --git a/vm_insnhelper.c b/vm_insnhelper.c index b1673db067..90c68d6a56 100644 --- a/vm_insnhelper.c +++ b/vm_insnhelper.c @@ -5308,7 +5308,7 @@ vm_trace(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp) return; } else { - rb_hook_list_t *global_hooks = rb_vm_global_hooks(ec); + rb_hook_list_t *global_hooks = rb_ec_ractor_hooks(ec); if (0) { fprintf(stderr, "vm_trace>>%4d (%4x) - %s:%d %s\n", diff --git a/vm_trace.c b/vm_trace.c index 50cdf5fcde..3835b18ae8 100644 --- a/vm_trace.c +++ b/vm_trace.c @@ -29,6 +29,7 @@ #include "mjit.h" #include "ruby/debug.h" #include "vm_core.h" +#include "ruby/ractor.h" #include "builtin.h" @@ -136,7 +137,7 @@ hook_list_connect(VALUE list_owner, rb_hook_list_t *list, rb_event_hook_t *hook, static void connect_event_hook(const rb_execution_context_t *ec, rb_event_hook_t *hook) { - rb_hook_list_t *list = rb_vm_global_hooks(ec); + rb_hook_list_t *list = rb_ec_ractor_hooks(ec); hook_list_connect(Qundef, list, hook, TRUE); } @@ -195,7 +196,7 @@ clean_hooks(const rb_execution_context_t *ec, rb_hook_list_t *list) } } - if (list == rb_vm_global_hooks(ec)) { + if (list == rb_ec_ractor_hooks(ec)) { /* global events */ update_global_event_hook(list->events); } @@ -220,8 +221,7 @@ clean_hooks_check(const rb_execution_context_t *ec, rb_hook_list_t *list) static int remove_event_hook(const rb_execution_context_t *ec, const rb_thread_t *filter_th, rb_event_hook_func_t func, VALUE data) { - rb_vm_t *vm = rb_ec_vm_ptr(ec); - rb_hook_list_t *list = &vm->global_hooks; + rb_hook_list_t *list = rb_ec_ractor_hooks(ec); int ret = 0; rb_event_hook_t *hook = list->hooks; @@ -374,7 +374,7 @@ rb_exec_event_hooks(rb_trace_arg_t *trace_arg, rb_hook_list_t *hooks, int pop_p) ec->trace_arg = trace_arg; /* only global hooks */ - exec_hooks_unprotected(ec, rb_vm_global_hooks(ec), trace_arg); + exec_hooks_unprotected(ec, rb_ec_ractor_hooks(ec), trace_arg); ec->trace_arg = prev_trace_arg; } } @@ -708,6 +708,7 @@ typedef struct rb_tp_struct { void (*func)(VALUE tpval, void *data); void *data; VALUE proc; + rb_ractor_t *ractor; VALUE self; } rb_tp_t; @@ -1113,7 +1114,9 @@ tp_call_trace(VALUE tpval, rb_trace_arg_t *trace_arg) (*tp->func)(tpval, tp->data); } else { - rb_proc_call_with_block((VALUE)tp->proc, 1, &tpval, Qnil); + if (tp->ractor == NULL || tp->ractor == GET_RACTOR()) { + rb_proc_call_with_block((VALUE)tp->proc, 1, &tpval, Qnil); + } } } @@ -1360,6 +1363,7 @@ tracepoint_new(VALUE klass, rb_thread_t *target_th, rb_event_flag_t events, void TypedData_Get_Struct(tpval, rb_tp_t, &tp_data_type, tp); tp->proc = proc; + tp->ractor = rb_ractor_shareable_p(proc) ? NULL : GET_RACTOR(); tp->func = func; tp->data = data; tp->events = events; @@ -1513,7 +1517,7 @@ tracepoint_stat_s(rb_execution_context_t *ec, VALUE self) rb_vm_t *vm = GET_VM(); VALUE stat = rb_hash_new(); - tracepoint_stat_event_hooks(stat, vm->self, vm->global_hooks.hooks); + tracepoint_stat_event_hooks(stat, vm->self, rb_ec_ractor_hooks(ec)->hooks); /* TODO: thread local hooks */ return stat; -- cgit v1.2.3