Bug #22439
closedSegfault in `Thread::Backtrace::Location#syntax_tree` (via `Exception#detailed_message` / error_highlight) when called from multiple Ractors
Description
Calling Exception#detailed_message concurrently from two or more Ractors crashes the VM with
[BUG] Segmentation fault on 4.1.0-preview1 and current master. The same script works on 4.0.6
and 4.0.7.
Reproduction¶
No gems are involved; error_highlight is loaded by default.
n = Integer(ARGV[0] || 2)
rs = Array.new(n) do |i|
Ractor.new(i) do |id|
500.times do |k|
begin
raise ArgumentError, "falha #{id}-#{k}"
rescue => e
e.detailed_message(highlight: false)
end
end
:ok
end
end
p rs.map(&:value)
| Version | Result |
|---|---|
| 4.0.6, 4.0.7 | [:ok, :ok] (8/8 runs) |
| 4.1.0-preview1 (2d08b5f42f) | segfault in 4/4 runs with 2 Ractors and 8/8 with 8 Ractors; no crash with 1 Ractor |
| 4.1.0dev master (b709bdb3e3) | segfault 6/6 |
Backtrace (master)¶
<internal:ast>:374: [BUG] Segmentation fault at 0x0000000000000030
-- Ruby level backtrace information ----------------------------------------
repro.rb:8:in 'detailed_message'
.../lib/ruby/4.1.0+5/error_highlight/core_ext.rb:43:in 'detailed_message'
.../lib/ruby/4.1.0+5/error_highlight/core_ext.rb:34:in 'generate_snippet'
.../lib/ruby/4.1.0+5/error_highlight/base.rb:57:in 'spot'
.../lib/ruby/4.1.0+5/error_highlight/base.rb:77:in 'find_node_from_loc'
<internal:ast>:478:in 'syntax_tree'
<internal:ast>:374:in 'syntax_tree'
-- C level backtrace information -------------------------------------------
rb_vm_bugreport
rb_ec_ractor_ptr / rb_current_execution_context / rb_current_ractor_raw / rb_current_ractor
vm_ic_update
rb_vm_opt_getconstant_path
vm_exec_core
rb_vm_exec
thread_start_func_2
The full output is attached (crash-output-master.txt).
Additional observations¶
-
The crash is reachable without error_highlight. Calling
e.backtrace_locations.first.syntax_treeinsiderescuein 2 Ractors gives the same crash and
stack. It crashed 1/3 runs on master and 0/3 on preview1, so thedetailed_messagescript above
is the more reliable reproducer. -
Some things that look similar do not crash.
caller_locations(0, 1).first.syntax_treein 2 Ractors works.Ruby::Prism.parse("1 + 1")in 2 Ractors works.
So the problem seems specific to backtrace locations taken from an exception, while the
constant cache inast.rbis updated from a non-main Ractor. -
With a single Ractor there is no crash, but error_highlight output regresses. Inside the
Ractor,detailed_messagereturns only the message, without the snippet:r = Ractor.new do begin nil.upcase rescue => e e.detailed_message(highlight: false) end end puts r.value # 4.0.7: undefined method 'upcase' for nil (NoMethodError)\n\n nil.upcase\n ^^^^^^^ # 4.1: undefined method 'upcase' for nil (NoMethodError)On 4.1 the snippet is still shown in the main Ractor.
-
This is easy to hit in practice. Any library that logs exceptions with
detailed_message
from inside Ractors can crash the process. I found it with theasyncgem, whose task-failure
logging (via theconsolegem) callsdetailed_message, running one reactor per Ractor. On
4.0.6 that same setup hangs instead of crashing; I have not diagnosed the 4.0.6 hang.
Related (but different) issues¶
- #22386: segfault when a Ractor helper thread reports an exception during teardown. It was
fixed before preview1, and this still reproduces on preview1 and master. - #21183: error_highlight raising
Ractor::IsolationErrorin non-main Ractors (fixed in 2025).
Environment and context¶
- Linux x86_64 (kernel 7.2, AMD Ryzen 7 5700U, 8C/16T). Also seen on Ubuntu 24.04, AMD EPYC
Genoa (KVM).- These scripts come out of a benchmark study comparing threads, Ractors and Fibers on Ruby 4.0 and
4.1. The code, raw results and other Ractor findings (I/O concurrency cap on 4.0.x, socket hangs
on 4.0.x) are public at: https://github.com/amalrik/ruby-ractors-study. The reproducers for this issue are in
upstream/ruby-4.1-detailed-message-ractors/
- These scripts come out of a benchmark study comparing threads, Ractors and Fibers on Ruby 4.0 and
Updated by mame (Yusuke Endoh) about 10 hours ago
- Related to Bug #22440: Referencing an autoload constant from multiple Ractors dumps core added
Updated by mame (Yusuke Endoh) about 10 hours ago
- Related to Bug #22442: Lazy loading of error_highlight etc. is skipped in threads and Ractors added
Updated by mame (Yusuke Endoh) about 10 hours ago
Thank you for the report!
I could reproduce the SEGV only with GCC 16 (GCC 13 and 15 did not reproduce it). Are you also using GCC 16 to build Ruby?
This ticket contained two different problems, so I have split it into:
- #22440: SEGV when referencing an autoload constant from multiple Ractors (
Ruby::Prismis autoloaded, which caused the crash here) - #22442: the lazy loading of error_highlight etc. is skipped in threads and Ractors (which is why the snippet was not shown)
If possible, I'd appreciate it if you could test with both patches attached to those tickets applied together.
Updated by amalrik (amalrik maia) about 6 hours ago
mame (Yusuke Endoh) wrote in #note-3:
Thank you for the report!
I could reproduce the SEGV only with GCC 16 (GCC 13 and 15 did not reproduce it). Are you also using GCC 16 to build Ruby?
This ticket contained two different problems, so I have split it into:
- #22440: SEGV when referencing an autoload constant from multiple Ractors (
Ruby::Prismis autoloaded, which caused the crash here)- #22442: the lazy loading of error_highlight etc. is skipped in threads and Ractors (which is why the snippet was not shown)
If possible, I'd appreciate it if you could test with both patches attached to those tickets applied together.
Thank you for the quick analysis and for splitting the ticket!
Yes, I'm using GCC 16. Both 4.1 builds I reported were compiled locally on Arch Linux:
ruby 4.1.0preview1 (2026-10-11 master 2d08b5f42f) +PRISM [x86_64-linux]
ruby 4.1.0dev (2026-10-14T14:33:24Z master b709bdb3e3) +PRISM [x86_64-linux]
CC: gcc (GCC) 16.2.1 20260810, optflags -O3 -fno-fast-math
Two corrections to my original report, sorry about them:
- The "Also seen on Ubuntu 24.04, AMD EPYC Genoa" line was wrong. I never ran this reproducer on that machine.
- The 4.0.6/4.0.7 binaries I used as the "works" baseline were prebuilt with GCC 10. So the version comparison in the report is confounded by the compiler, which is consistent with your finding.
I tested both patches applied together: https://github.com/ruby/ruby/pull/19348 and https://github.com/ruby/ruby/pull/19352, cherry-picked onto master 3d168b1. I built with the same GCC 16.2.1 and ran each script N times:
| Script | master b709bdb3e3 (no patches) | master 3d168b1 + both patches |
|---|---|---|
| #22440 reproducer (autoload constant from 8 Ractors) | 10/10 SEGV | 10/10 ok |
#22439 detailed_message from 2 Ractors |
10/10 SEGV | 10/10 ok |
#22439 e.backtrace_locations.first.syntax_tree from 2 Ractors |
1/10 SEGV | 10/10 ok |
#22442 snippet present in both Ractors (nil.upcase in 2 Ractors) |
not testable (SEGV) | 5/5 runs, snippet in both |
So with both patches, everything in this ticket is fixed on my machine. Thanks!
Updated by mame (Yusuke Endoh) 12 minutes ago
- Status changed from Open to Closed
Thank you for confirming the patches! I think this is resolved, so I'm closing this ticket.