From: eregontp@... Date: 2021-01-07T13:22:38+00:00 Subject: [ruby-core:101972] [Ruby master Bug#17420] Unsafe mutation of $" when doing non-RubyGems require in Ractor Issue #17420 has been updated by Eregon (Benoit Daloze). ko1 (Koichi Sasada) wrote in #note-7: > If we allow to require from non-main ractors, the only problem is `$LOADED_FEATURES`? Not only, as we see above RubyGems uses a Monitor, and that doesn't work with Ractor. Making the entire logic for RubyGems' #require safe is probably not easy. And as Marc-Andr� says, any constant assignment with something not Ractor-shareable would fail, so basically almost every gem would fail to load in a Ractor. So I think loading code in the main Ractor is the only realistic solution here. Either by having a clear error if `require` is used on non-main Ractor, or delegate the require to the main Ractor main Thread. One issue though is such a "delegation" really means interrupting the main Thread potentially at a random place (via interrupt checks I guess), which can be expensive (it might cancel no GVL code, which might need to redo a lot of work), and arbitrarily delayed (e.g., if the main Thread is in native code). ---------------------------------------- Bug #17420: Unsafe mutation of $" when doing non-RubyGems require in Ractor https://bugs.ruby-lang.org/issues/17420#change-89824 * Author: Eregon (Benoit Daloze) * Status: Open * Priority: Normal * Assignee: ko1 (Koichi Sasada) * ruby -v: ruby 3.0.0dev (2020-12-16T10:12:48Z master a9a7f4d8b8) [x86_64-linux] * Backport: 2.5: UNKNOWN, 2.6: UNKNOWN, 2.7: UNKNOWN ---------------------------------------- With an empty file `a.rb`: ``` $ ruby --disable-gems -e 'Ractor.new { puts $" }.take' -e:1:in `block in
': can not access global variables $" from non-main Ractors (RuntimeError) ``` That is expected, given the rules for global variables. ``` ruby --disable-gems -e 'Ractor.new { require "./a.rb"; }.take; p $"' [... , "/home/eregon/a.rb"] ``` Is it OK that the Ractor can do `require`, which does modify `$"`? I think it's not, and it might lead to segfaults if e.g. the main Ractor mutates `$"` in parallel to some other Ractor doing `require`. Probably `require` needs to be forbidden in non-main Ractors (it does mutate `$"`, so it's logical), or there needs to be always VM-global synchronization on any access to `$"` (otherwise, segfaults are possible). The latter doesn't seem reasonable, especially when considering the user might do `$".each { ... }`. --- Note that RubyGems' `require` does not work on non-main Ractors (pretty much expected given it depends on a lot of global state): ``` $ ruby -e 'Ractor.new { require "./a.rb"; }.take' :37:in `require': can not access non-shareable objects in constant Kernel::RUBYGEMS_ACTIVATION_MONITOR by non-main ractor. (NameError) ``` This probably also has consequences for `autoload`. Maybe the `zeitwerk` gem can help with the mode to resolve all autoload at once. -- https://bugs.ruby-lang.org/ Unsubscribe: