Bug #22440
closedReferencing an autoload constant from multiple Ractors dumps core
Description
Referencing an autoload constant from multiple Ractors in parallel may cause a SEGV:
Reproduced with GCC 16 on Ubuntu 26.04. Not reproduced with GCC 13 / 15.
Cause:
- GCC 16 computes the address of the TLS variable (
ruby_current_ec) at the entry ofrb_vm_opt_getconstant_path, and reuses it within the function. - When
vm_get_ev_const_chainblocks waiting for an autoload, the M:N thread scheduler may resume the thread on a different native thread. - After that,
GET_RACTOR()invm_ic_update(inlined) reads the TLS of the previous native thread, refers to an invalid value, and SEGVs.
Proposed fix: pass ec (already an argument of rb_vm_opt_getconstant_path) to vm_ic_update, and use rb_ec_ractor_ptr(ec) instead of GET_RACTOR().
https://github.com/ruby/ruby/pull/19348
Note: the SEGV in #22439 is this issue, triggered by the autoload of Ruby::Prism. Since #22439 also involves another problem, I created this ticket dedicated to the autoload + Ractor issue.
Updated by mame (Yusuke Endoh) 1 day ago
- Related to Bug #22439: Segfault in `Thread::Backtrace::Location#syntax_tree` (via `Exception#detailed_message` / error_highlight) when called from multiple Ractors added
Updated by mame (Yusuke Endoh) about 16 hours ago
- Status changed from Assigned to Closed
Applied in changeset git|8a060f90ba36441cfeb509eacb10f609314f5bfe.
Fix SEGV when referencing an autoload constant from multiple Ractors
vm_ic_update used GET_RACTOR() after the constant lookup. The lookup may
block waiting for an autoload, and under the M:N thread scheduler the
thread may then be resumed on a different native thread. Since
vm_ic_update is inlined into rb_vm_opt_getconstant_path, a compiler can
reuse the TLS address computed at the function entry (GCC 16 does), so
GET_RACTOR() read the ec of the previous native thread and crashed.
autoload :Foo, "./foo"
p 8.times.map { Ractor.new { Foo } }.map(&:value)
#=> [BUG] Segmentation fault at 0x0000000000000030
Use the ec passed to rb_vm_opt_getconstant_path instead.
[Bug #22440]
Co-Authored-By: Claude Opus 5.5 noreply@anthropic.com