📑
[Bug #21649] singleton_class 経由で Ractor 内でオブジェクトが書き換えられるバグ報告
[Bug #21649] Ractors can access non-shareable object through singleton classes
-
Ractor.newに渡したオブジェクトはブロック内では別のオブジェクトとして扱われるので通常は元のオブジェクトには影響は与えない
homu = "homu"
p homu.object_id # => 16
r = Ractor.new(homu) { |name|
# スコープの外とは別のオブジェクトとして扱われる
p name.object_id # => 24
# 副作用があるメソッドを呼び出しても元のオブジェクトには影響は与えない
name.upcase!
}
r.take
p homu
# => "homu"
- これは
HashやArrayでネストしている場合でも同様
users = [
{ name: "homu", age: 14 }
]
p users[0][:name].object_id # => 16
# ネストしたオブジェクトの場合でもコピーされる
r = Ractor.new(users) { |users|
p users[0][:name].object_id # => 24
users[0][:name].upcase!
}
r.take
p users[0][:name]
# => "homu"
- なんですが次のように
singleton_classを渡した場合には#attached_object経由で元のオブジェクトを書き換えることができるというバグ報告
homu = "homu"
p homu.object_id # => 24
r = Ractor.new(homu.singleton_class) { |singleton_klass|
# #attached_object は元々のオブジェクトを取得することができる
p singleton_klass.attached_object # => "homu"
# #attached_object は元々のオブジェクトを参照している
p singleton_klass.attached_object.object_id # => 16
# なので副作用のあるメソッドを呼び出すとスコープの外のオブジェクトも変わってしまう
singleton_klass.attached_object.upcase!
}
r.take
p homu # => "HOMU"
- すごいハックですね
- 意図的に
singleton_classを渡すことはあるのかなあ…
Discussion