summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKoichi Sasada <ko1@atdot.net>2021-12-09 03:58:44 +0900
committerKoichi Sasada <ko1@atdot.net>2021-12-09 16:20:04 +0900
commitcce331272b07636d536c8227288ab3fbcf24e2aa (patch)
tree167882704bfd85c0573b46c2007116a503b8c153
parentc5f68a9a24c4e25f551108bda4738b1000d7b197 (diff)
`Ractor.make_shareable` checks proc's sefl
`Ractor.make_shareable(proc_obj)` raises an `IsolationError` if the self of `proc_obj` is not a shareable object. [Bug #18243]
Notes
Notes: Merged: https://github.com/ruby/ruby/pull/5232
-rw-r--r--bootstraptest/test_ractor.rb32
-rw-r--r--test/ruby/test_iseq.rb12
-rw-r--r--vm.c4
3 files changed, 32 insertions, 16 deletions
diff --git a/bootstraptest/test_ractor.rb b/bootstraptest/test_ractor.rb
index ef1e6afcac..e259684974 100644
--- a/bootstraptest/test_ractor.rb
+++ b/bootstraptest/test_ractor.rb
@@ -190,7 +190,7 @@ assert_equal '[:ok, :ok, :ok]', %q{
# Ractor.make_shareable issue for locals in proc [Bug #18023]
assert_equal '[:a, :b, :c, :d, :e]', %q{
v1, v2, v3, v4, v5 = :a, :b, :c, :d, :e
- closure = Proc.new { [v1, v2, v3, v4, v5] }
+ closure = Ractor.current.instance_eval{ Proc.new { [v1, v2, v3, v4, v5] } }
Ractor.make_shareable(closure).call
}
@@ -198,13 +198,15 @@ assert_equal '[:a, :b, :c, :d, :e]', %q{
# Ractor.make_shareable issue for locals in proc [Bug #18023]
assert_equal '[:a, :b, :c, :d, :e, :f, :g]', %q{
a = :a
- closure = -> {
- b, c, d = :b, :c, :d
+ closure = Ractor.current.instance_eval do
-> {
- e, f, g = :e, :f, :g
- -> { [a, b, c, d, e, f, g] }
+ b, c, d = :b, :c, :d
+ -> {
+ e, f, g = :e, :f, :g
+ -> { [a, b, c, d, e, f, g] }
+ }.call
}.call
- }.call
+ end
Ractor.make_shareable(closure).call
}
@@ -1276,9 +1278,13 @@ assert_equal 'true', %q{
# Ractor.make_shareable(a_proc) makes a proc shareable.
assert_equal 'true', %q{
a = [1, [2, 3], {a: "4"}]
- pr = Proc.new do
- a
+
+ pr = Ractor.current.instance_eval do
+ Proc.new do
+ a
+ end
end
+
Ractor.make_shareable(a) # referred value should be shareable
Ractor.make_shareable(pr)
Ractor.shareable?(pr)
@@ -1326,10 +1332,12 @@ assert_equal '1', %q{
# Ractor.make_shareable(a_proc) makes a proc shareable.
assert_equal 'can not make a Proc shareable because it accesses outer variables (a).', %q{
a = b = nil
- pr = Proc.new do
- c = b # assign to a is okay because c is block local variable
- # reading b is okay
- a = b # assign to a is not allowed #=> Ractor::Error
+ pr = Ractor.current.instance_eval do
+ Proc.new do
+ c = b # assign to a is okay because c is block local variable
+ # reading b is okay
+ a = b # assign to a is not allowed #=> Ractor::Error
+ end
end
begin
diff --git a/test/ruby/test_iseq.rb b/test/ruby/test_iseq.rb
index ac191531de..aa0bf35b80 100644
--- a/test/ruby/test_iseq.rb
+++ b/test/ruby/test_iseq.rb
@@ -129,7 +129,7 @@ class TestISeq < Test::Unit::TestCase
def test_lambda_with_ractor_roundtrip
iseq = compile(<<~EOF, __LINE__+1)
x = 42
- y = lambda { x }
+ y = nil.instance_eval{ lambda { x } }
Ractor.make_shareable(y)
y.call
EOF
@@ -148,16 +148,20 @@ class TestISeq < Test::Unit::TestCase
def test_ractor_unshareable_outer_variable
name = "\u{2603 26a1}"
- y = eval("proc {#{name} = nil; proc {|x| #{name} = x}}").call
+ y = nil.instance_eval do
+ eval("proc {#{name} = nil; proc {|x| #{name} = x}}").call
+ end
assert_raise_with_message(ArgumentError, /\(#{name}\)/) do
Ractor.make_shareable(y)
end
- y = eval("proc {#{name} = []; proc {|x| #{name}}}").call
+ y = nil.instance_eval do
+ eval("proc {#{name} = []; proc {|x| #{name}}}").call
+ end
assert_raise_with_message(Ractor::IsolationError, /`#{name}'/) do
Ractor.make_shareable(y)
end
obj = Object.new
- def obj.foo(*) ->{super} end
+ def obj.foo(*) nil.instance_eval{ ->{super} } end
assert_raise_with_message(Ractor::IsolationError, /hidden variable/) do
Ractor.make_shareable(obj.foo)
end
diff --git a/vm.c b/vm.c
index ad687d579a..73d6cd9d5d 100644
--- a/vm.c
+++ b/vm.c
@@ -1181,6 +1181,10 @@ rb_proc_ractor_make_shareable(VALUE self)
rb_proc_t *proc = (rb_proc_t *)RTYPEDDATA_DATA(self);
if (proc->block.type != block_type_iseq) rb_raise(rb_eRuntimeError, "not supported yet");
+ if (!rb_ractor_shareable_p(vm_block_self(&proc->block))) {
+ rb_raise(rb_eRactorIsolationError, "Proc's self is not shareable");
+ }
+
VALUE read_only_variables = Qfalse;
if (iseq->body->outer_variables) {