🎉

[Bug #19765] Ractor.make_shareable に Method#proc を渡したときに意図しない挙動になるバグ報告

2024/05/08に公開

[Bug #19765] Ractor.make_shareable ignores self of a proc created from a Method

  • Ractor では任意のオブジェクトを複数の Ractor で参照する場合に不変にする必要がある
  • それを行うメソッドとして Ractor.make_shareable が存在している
obj1 = "hoge"

# Ractor.make_shareable すると引数が不変になる
pp obj1.frozen?   # => false
Ractor.make_shareable obj1
pp obj1.frozen?   # => true

# また freeze とは違いネストしているオブジェクトも全て freeze される
obj2 = ["hoge", [{ name: "homu" }]]
Ractor.make_shareable obj2
pp obj2[0].frozen?   # => true
pp obj2[1][0][:name].frozen?   # => true
  • また、次のように Proc オブジェクトや Method オブジェクトはエラーになる
str = ""

a = str.instance_exec { proc { to_s } }
Ractor.make_shareable a
# => <internal:ractor>:820:in `make_shareable': Proc's self is not shareable: #<Proc:0x00000001064b62c8 (irb):1> (Ractor::IsolationError)

b = str.instance_exec { method(:to_s) }
Ractor.make_shareable b
# => <internal:ractor>:820:in `make_shareable': can not make shareable object for #<Method: String#to_s()> (Ractor::Error)
  • ただし、次のように Method#proc の場合だとエラーにならないというバグ報告
str = ""

a = str.instance_exec { method(:to_s).to_proc }
# Method#to_proc を渡してもエラーにならない
Ractor.make_shareable a
# => no error

pp a.call   # => ""

# a は不変であるはずなのに結果が変わってしまう
str[0] = "!"
pp a.call   # => "!"
GitHubで編集を提案

Discussion