ruby-changes:63126
From: Koichi <ko1@a...>
Date: Fri, 25 Sep 2020 20:37:56 +0900 (JST)
Subject: [ruby-changes:63126] caaa36b4e6 (master): prohibi method call by defined_method in other racotrs
https://git.ruby-lang.org/ruby.git/commit/?id=caaa36b4e6 From caaa36b4e6d0d59f0aa21049c063b140aa5aae4f Mon Sep 17 00:00:00 2001 From: Koichi Sasada <ko1@a...> Date: Fri, 25 Sep 2020 18:31:04 +0900 Subject: prohibi method call by defined_method in other racotrs We can not call a non-isolated Proc in multiple ractors. diff --git a/bootstraptest/test_ractor.rb b/bootstraptest/test_ractor.rb index ff99521..a71f006 100644 --- a/bootstraptest/test_ractor.rb +++ b/bootstraptest/test_ractor.rb @@ -724,6 +724,17 @@ assert_equal 'can not set constants with non-shareable objects by non-main Racto https://github.com/ruby/ruby/blob/trunk/bootstraptest/test_ractor.rb#L724 end } +# define_method is not allowed +assert_equal "defined in a different Ractor", %q{ + str = "foo" + define_method(:buggy){|i| str << "#{i}"} + begin + Ractor.new{buggy(10)}.take + rescue => e + e.cause.message + end +} + # Immutable Array and Hash are shareable, so it can be shared with constants assert_equal '[1000, 3]', %q{ A = Array.new(1000).freeze # [nil, ...] diff --git a/method.h b/method.h index dae0a4f..5b6fe2d 100644 --- a/method.h +++ b/method.h @@ -159,6 +159,7 @@ typedef struct rb_method_refined_struct { https://github.com/ruby/ruby/blob/trunk/method.h#L159 typedef struct rb_method_bmethod_struct { VALUE proc; /* should be marked */ struct rb_hook_list_struct *hooks; + VALUE defined_ractor; } rb_method_bmethod_t; enum method_optimized_type { diff --git a/vm_insnhelper.c b/vm_insnhelper.c index 30177b7..3d2667d 100644 --- a/vm_insnhelper.c +++ b/vm_insnhelper.c @@ -2667,9 +2667,14 @@ vm_call_bmethod_body(rb_execution_context_t *ec, struct rb_calling_info *calling https://github.com/ruby/ruby/blob/trunk/vm_insnhelper.c#L2667 rb_proc_t *proc; VALUE val; const struct rb_callcache *cc = cd->cc; + const rb_callable_method_entry_t *cme = vm_cc_cme(cc); + + if (cme->def->body.bmethod.defined_ractor != rb_ec_ractor_ptr(ec)->self) { + rb_raise(rb_eRuntimeError, "defined in a different Ractor"); + } /* control block frame */ - GetProcPtr(vm_cc_cme(cc)->def->body.bmethod.proc, proc); + GetProcPtr(cme->def->body.bmethod.proc, proc); val = rb_vm_invoke_bmethod(ec, proc, calling->recv, calling->argc, argv, calling->kw_splat, calling->block_handler, vm_cc_cme(cc)); return val; diff --git a/vm_method.c b/vm_method.c index 0428ae6..de48dc6 100644 --- a/vm_method.c +++ b/vm_method.c @@ -430,6 +430,7 @@ rb_method_definition_set(const rb_method_entry_t *me, rb_method_definition_t *de https://github.com/ruby/ruby/blob/trunk/vm_method.c#L430 } case VM_METHOD_TYPE_BMETHOD: RB_OBJ_WRITE(me, &def->body.bmethod.proc, (VALUE)opts); + RB_OBJ_WRITE(me, &def->body.bmethod.defined_ractor, GET_THREAD()->ractor->self); return; case VM_METHOD_TYPE_NOTIMPLEMENTED: setup_method_cfunc_struct(UNALIGNED_MEMBER_PTR(def, body.cfunc), rb_f_notimplement, -1); @@ -471,6 +472,7 @@ method_definition_reset(const rb_method_entry_t *me) https://github.com/ruby/ruby/blob/trunk/vm_method.c#L472 break; case VM_METHOD_TYPE_BMETHOD: RB_OBJ_WRITTEN(me, Qundef, def->body.bmethod.proc); + RB_OBJ_WRITTEN(me, Qundef, def->body.bmethod.defined_ractor); /* give up to check all in a list */ if (def->body.bmethod.hooks) rb_gc_writebarrier_remember((VALUE)me); break; -- cgit v0.10.2 -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/