Bug #22442
closedLazy loading of error_highlight etc. is skipped in threads and Ractors
Description
#21951 made error_highlight / did_you_mean / syntax_suggest lazily loaded.
When the lazy loading is triggered concurrently from threads or Ractors, the decoration may be skipped.
# repro.rb
rs = 2.times.map do
Ractor.new do
nil.upcase
rescue => e
e.detailed_message(highlight: false)
end
end
rs.each { puts it.value, "" }
Expected:
$ ruby repro.rb
undefined method 'upcase' for nil (NoMethodError)
nil.upcase
^^^^^^^
undefined method 'upcase' for nil (NoMethodError)
nil.upcase
^^^^^^^
Actual:
$ ruby repro.rb
undefined method 'upcase' for nil (NoMethodError)
nil.upcase
^^^^^^^
undefined method 'upcase' for nil (NoMethodError)
Cause: the first caller of detailed_message sets a flag when it starts loading. So when another thread or Ractor calls it during the load, it returns without decoration instead of waiting for the load to complete.
Fix: fire the autoload instead of calling rb_require_string, so that the autoload's synchronization prevents the skip.
https://github.com/ruby/ruby/pull/19352
Also, because rb_require_string was used, a newer version installed by gem install error_highlight was not used.
Firing the autoload respects the monkeypatch of Kernel#require, so the newer version of error_highlight will be used.
Note: this is why the snippet is not shown in #22439.