Project

General

Profile

Actions

Bug #21257

open

YJIT can generate infinite loop when OOM

Added by rianmcguire (Rian McGuire) 7 days ago. Updated 7 days ago.

Status:
Assigned
Assignee:
Target version:
-
[ruby-core:121597]

Description

We've found an edge case where YJIT can generate an infinite loop (jump to the same address) when it's out-of-memory.

Reproduction:

def first
  second
end

def second
  ::File
end

# Make `second` side exit on its first instruction
trace = TracePoint.new(:line) { }
trace.enable(target: method(:second))

32.times do |i|
  puts i
  first

  if i == 29
    # We've JITed the methods now - trigger the bug

    # Trigger a constant cache miss in rb_vm_opt_getconstant_path (in `second`) next time it's called
    module InvalidateConstantCache
      File = nil
    end

    # nb. this only works in yjit dev mode
    RubyVM::YJIT.simulate_oom!
  end
end

This hangs indefinitely when run with YJIT (./configure --enable-yjit=dev is required for simulate_oom).

If we attach a debugger to the Ruby process at this point, it's stuck in an infinite loop:

$ lldb -p 9753
(lldb) process attach --pid 9753
Process 9753 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = signal SIGSTOP
    frame #0: 0x0000000104b202b8
->  0x104b202b8: b      0x104b202b8
    0x104b202bc: nop
    0x104b202c0: nop
    0x104b202c4: nop
Target 0: (ruby) stopped.
Executable module set to "/Users/rian/opt/ruby/bin/ruby".
Architecture set to: arm64-apple-macosx-.

We've reproduced this on:

ruby 3.3.6 (2024-11-05 revision 75015d4c1f) [x86_64-linux]
ruby 3.4.2 (2025-02-15 revision d2930f8e7a) +PRISM [arm64-darwin23]
ruby 3.5.0dev (2025-04-08T06:46:45Z master b68fe530f1) +PRISM [arm64-darwin23]
Actions

Also available in: Atom PDF

Like2
Like0Like0