mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
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]
This commit is contained in:
parent
c5f68a9a24
commit
cce331272b
Notes:
git
2021-12-09 16:20:29 +09:00
3 changed files with 32 additions and 16 deletions
|
@ -190,7 +190,7 @@ assert_equal '[:ok, :ok, :ok]', %q{
|
||||||
# Ractor.make_shareable issue for locals in proc [Bug #18023]
|
# Ractor.make_shareable issue for locals in proc [Bug #18023]
|
||||||
assert_equal '[:a, :b, :c, :d, :e]', %q{
|
assert_equal '[:a, :b, :c, :d, :e]', %q{
|
||||||
v1, v2, v3, v4, v5 = :a, :b, :c, :d, :e
|
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
|
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]
|
# Ractor.make_shareable issue for locals in proc [Bug #18023]
|
||||||
assert_equal '[:a, :b, :c, :d, :e, :f, :g]', %q{
|
assert_equal '[:a, :b, :c, :d, :e, :f, :g]', %q{
|
||||||
a = :a
|
a = :a
|
||||||
closure = -> {
|
closure = Ractor.current.instance_eval do
|
||||||
|
-> {
|
||||||
b, c, d = :b, :c, :d
|
b, c, d = :b, :c, :d
|
||||||
-> {
|
-> {
|
||||||
e, f, g = :e, :f, :g
|
e, f, g = :e, :f, :g
|
||||||
-> { [a, b, c, d, e, f, g] }
|
-> { [a, b, c, d, e, f, g] }
|
||||||
}.call
|
}.call
|
||||||
}.call
|
}.call
|
||||||
|
end
|
||||||
|
|
||||||
Ractor.make_shareable(closure).call
|
Ractor.make_shareable(closure).call
|
||||||
}
|
}
|
||||||
|
@ -1276,9 +1278,13 @@ assert_equal 'true', %q{
|
||||||
# Ractor.make_shareable(a_proc) makes a proc shareable.
|
# Ractor.make_shareable(a_proc) makes a proc shareable.
|
||||||
assert_equal 'true', %q{
|
assert_equal 'true', %q{
|
||||||
a = [1, [2, 3], {a: "4"}]
|
a = [1, [2, 3], {a: "4"}]
|
||||||
pr = Proc.new do
|
|
||||||
|
pr = Ractor.current.instance_eval do
|
||||||
|
Proc.new do
|
||||||
a
|
a
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
Ractor.make_shareable(a) # referred value should be shareable
|
Ractor.make_shareable(a) # referred value should be shareable
|
||||||
Ractor.make_shareable(pr)
|
Ractor.make_shareable(pr)
|
||||||
Ractor.shareable?(pr)
|
Ractor.shareable?(pr)
|
||||||
|
@ -1326,11 +1332,13 @@ assert_equal '1', %q{
|
||||||
# Ractor.make_shareable(a_proc) makes a proc shareable.
|
# Ractor.make_shareable(a_proc) makes a proc shareable.
|
||||||
assert_equal 'can not make a Proc shareable because it accesses outer variables (a).', %q{
|
assert_equal 'can not make a Proc shareable because it accesses outer variables (a).', %q{
|
||||||
a = b = nil
|
a = b = nil
|
||||||
pr = Proc.new do
|
pr = Ractor.current.instance_eval do
|
||||||
|
Proc.new do
|
||||||
c = b # assign to a is okay because c is block local variable
|
c = b # assign to a is okay because c is block local variable
|
||||||
# reading b is okay
|
# reading b is okay
|
||||||
a = b # assign to a is not allowed #=> Ractor::Error
|
a = b # assign to a is not allowed #=> Ractor::Error
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
begin
|
begin
|
||||||
Ractor.make_shareable(pr)
|
Ractor.make_shareable(pr)
|
||||||
|
|
|
@ -129,7 +129,7 @@ class TestISeq < Test::Unit::TestCase
|
||||||
def test_lambda_with_ractor_roundtrip
|
def test_lambda_with_ractor_roundtrip
|
||||||
iseq = compile(<<~EOF, __LINE__+1)
|
iseq = compile(<<~EOF, __LINE__+1)
|
||||||
x = 42
|
x = 42
|
||||||
y = lambda { x }
|
y = nil.instance_eval{ lambda { x } }
|
||||||
Ractor.make_shareable(y)
|
Ractor.make_shareable(y)
|
||||||
y.call
|
y.call
|
||||||
EOF
|
EOF
|
||||||
|
@ -148,16 +148,20 @@ class TestISeq < Test::Unit::TestCase
|
||||||
|
|
||||||
def test_ractor_unshareable_outer_variable
|
def test_ractor_unshareable_outer_variable
|
||||||
name = "\u{2603 26a1}"
|
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
|
assert_raise_with_message(ArgumentError, /\(#{name}\)/) do
|
||||||
Ractor.make_shareable(y)
|
Ractor.make_shareable(y)
|
||||||
end
|
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
|
assert_raise_with_message(Ractor::IsolationError, /`#{name}'/) do
|
||||||
Ractor.make_shareable(y)
|
Ractor.make_shareable(y)
|
||||||
end
|
end
|
||||||
obj = Object.new
|
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
|
assert_raise_with_message(Ractor::IsolationError, /hidden variable/) do
|
||||||
Ractor.make_shareable(obj.foo)
|
Ractor.make_shareable(obj.foo)
|
||||||
end
|
end
|
||||||
|
|
4
vm.c
4
vm.c
|
@ -1181,6 +1181,10 @@ rb_proc_ractor_make_shareable(VALUE self)
|
||||||
rb_proc_t *proc = (rb_proc_t *)RTYPEDDATA_DATA(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 (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;
|
VALUE read_only_variables = Qfalse;
|
||||||
|
|
||||||
if (iseq->body->outer_variables) {
|
if (iseq->body->outer_variables) {
|
||||||
|
|
Loading…
Reference in a new issue