From: "tagomoris (Satoshi Tagomori) via ruby-core" Date: 2026-05-02T15:02:00+00:00 Subject: [ruby-core:125393] [Ruby Feature#21953] Allow accessing unshareable objects within a Ractor-local Ruby Box Issue #21953 has been updated by tagomoris (Satoshi Tagomori). Basically, I agree to this proposal. The described use case is very clear and understandable to me. Technically, we can find several things to be considered. 1) It's not clear how a box is tied with a ractor This proposal is based on an idea that a "Ractor-local" box (for non-main ractors). But currently, Ruby::Box instances (kind of Module) are shareable objects without any information that tell us which Ractor the box was created in. 2) Non-boxed global variables > Currently, non-main ractors prohibit access to the following objects to prevent data races: > > Global variables > Class variables > Unshareable class instance variables > Unshareable constants Class variables, Class instance variables and constants (under a Class) seem to not have any problems to be handled as Ractor-local variables if the Class is created in a user box and the box is a non-main Ractor-local box. We can see the box of the class's classext to know a Class was originally created in a box or not. Global variables are cached/separated by Ruby Box in general. But some of global variables are out of Ruby Box control - for example, `$!` and `$_`. (See https://github.com/ruby/ruby/pull/16303 for example). So the Ractor-local box's global variable management should take care of those global variables. In my instant idea, accessing "Box ready" or "Box dynamic" global variables should be prohibited unless it is marked as Ractor local. But I may miss something in corner cases. ---------------------------------------- Feature #21953: Allow accessing unshareable objects within a Ractor-local Ruby Box https://bugs.ruby-lang.org/issues/21953#change-117156 * Author: tikkss (Tsutomu Katsube) * Status: Open ---------------------------------------- ### Status Currently, non-main ractors prohibit access to the following objects to prevent data races: * Global variables * Class variables * Unshareable class instance variables * Unshareable constants ### Proposal I would like to propose that allow reading/writing unshareable objects inside a Ruby Box created in a non-main ractor: ```ruby # lib/x.rb class X # can write unshareable objects XXX = "1" @@cvar = "1" @ivar = "1" class << self def cvar; @@cvar; end def ivar; @ivar; end end end # can read unshareable objects $LOAD_PATH # => returns $LOAD_PATH includes lib directory X.cvar # => "1" X.ivar # => "1" X::XXX # => "1" # main.rb Ractor.new do local_box = Ruby::Box.new local_box.eval <<~RUBY base_dir = File.expand_path(File.dirname(__FILE__)) lib_dir = File.join(base_dir, "lib") # can write unshareable objects $LOAD_PATH.unshift(lib_dir) RUBY local_box.require("x") x = local_box::X.new end.join ``` Ruby Box can isolate global/class variables, class/module definitions from other boxes. A Ruby Box created inside a non-main ractor cannot be accessed from other ractor. If that is the case, wouldn���t it be fine to access unshareable objects inside that box? So I would like to propose that allow reading/writing unshareable objects inside a Ruby Box created in a non-main ractor. ### Background We are working on implementing a Ractor based parallel test runner for the test-unit gem. Ractor is a great for parallel processing. However, many existing libraries still rely on class variables or class instance variables for configuration. Ideally, we should reduce the use of class variables or class instance variables. Currently, we tried fixing several non-shareable objects, but we could not resolve all of them yet. We will continue working on this issue, but we are also exploring other approaches. This is the idea begind this proposal. I think the work needed to make objects shareable when running exisiting libraries with Ractor can be reduced. ### FAQ Q: Can we create a Ruby Box inside a non-main ractor? A: Yes: ```ruby Ractor.new {Ruby::Box.new}.join ``` Q: Is a Ruby Box created in a non-main ractor truly inaccessible from other ractor? A: No. I'm not sure if it's intentional, but a Ruby Box is a shareable object. Also, it can be accessed from the main Ractor by using `Ractor#value`: ```ruby Ractor.shareable?(Ruby::Box.new) # => true ``` ```ruby Ractor.new {Ruby::Box.new}.value # => # ``` To implement this proposal, Ruby Box may need to be an unshareable object, and passing it with `Ractor#value` may need to be disallowed. ---Files-------------------------------- 1000.html (1.01 KB) 10000.html (1.02 KB) 100000.html (1.02 KB) -- https://bugs.ruby-lang.org/ ______________________________________________ ruby-core mailing list -- ruby-core@ml.ruby-lang.org To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org ruby-core info -- https://ml.ruby-lang.org/mailman3/lists/ruby-core.ml.ruby-lang.org/