[前][次][番号順一覧][スレッド一覧]

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/

[前][次][番号順一覧][スレッド一覧]