Project

General

Profile

Actions

Bug #21941

open

Local variable becomes nil when YJIT enabled mid-method with fork/signal/ensure

Bug #21941: Local variable becomes nil when YJIT enabled mid-method with fork/signal/ensure
1

Added by nicholasdower (Nick Dower) about 12 hours ago. Updated about 11 hours ago.

Status:
Open
Assignee:
Target version:
-
ruby -v:
ruby 4.0.0 (2025-12-25 revision 553f1675f3) +PRISM [arm64-darwin25]
[ruby-core:124920]

Description

The following code results in the read local variable becoming nil, even though it is never reassigned:

def run
  fork_safe = ->(t) { t }
  RubyVM::YJIT.enable

  read, wakeup = IO.pipe
  Signal.trap("SIGCHLD") { wakeup.write("!") }

  begin
    while true
      begin
        fork { exit }

        next if read.wait_readable
      rescue Interrupt
      end
    end
  ensure
  end
end

run

Error:

repro.rb:13:in 'Object#run': undefined method 'wait_readable' for nil (NoMethodError)

        next if read.wait_readable
                    ^^^^^^^^^^^^^^
	from repro.rb:21:in '<main>'

See also:
https://github.com/puma/puma/issues/3620
https://github.com/Shopify/ruby/issues/625

Updated by byroot (Jean Boussier) about 12 hours ago Actions #1 [ruby-core:124921]

  • Assignee set to jit
  • Backport changed from 3.2: UNKNOWN, 3.3: UNKNOWN, 3.4: UNKNOWN, 4.0: UNKNOWN to 3.2: DONTNEED, 3.3: DONTNEED, 3.4: REQUIRED, 4.0: REQUIRED

Reduced even further:

def run
  fork_safe = ->(t) { t }
  RubyVM::YJIT.enable

  read, wakeup = IO.pipe
  wakeup.write("!")

  begin
    while true
      begin
        next if read.wait_readable
      rescue Interrupt
      end
    end
  ensure
  end
end

run

Updated by byroot (Jean Boussier) about 12 hours ago Actions #2 [ruby-core:124922]

Reduced some more, no IO or anything:

def run
  fork_safe = ->(t) { t }
  RubyVM::YJIT.enable

  i = 0

  begin
    while i < 100
      i += 1
      p i
      begin
        next if i
      rescue Interrupt
      end
    end
  ensure
  end
  p :ok
end

run
Actions

Also available in: PDF Atom