Issue #21926 has been updated by luke-gru (Luke Gruber). Backport changed from 3.2: UNKNOWN, 3.3: UNKNOWN, 3.4: UNKNOWN, 4.0: UNKNOWN to 3.2: UNKNOWN, 3.3: UNKNOWN, 3.4: REQUIRED, 4.0: REQUIRED Thank you for the nice reproduction! We have a fix coming, and it will probably be backported to 3.4 and 4.0 as well. The fix is at https://github.com/ruby/ruby/pull/16307. ---------------------------------------- Bug #21926: Thread#value on popen3 wait thread hangs in finalizer https://bugs.ruby-lang.org/issues/21926#change-116593 * Author: stevecrozz (Stephen Crosby) * Status: Open * ruby -v: 3.3.7 * Backport: 3.2: UNKNOWN, 3.3: UNKNOWN, 3.4: REQUIRED, 4.0: REQUIRED ---------------------------------------- Calling Thread#value on an Open3.popen3 wait thread from a finalizer completes in Ruby 3.2 but hangs in Ruby 3.3+. See repro.rb below. When the Ruby process hangs in these conditions, it no longer responds to signals and it seems to be unable to run any other threads. This affects the schmooze gem (and potentially other code using Open3.popen3 with finalizers), causing test suites to hang intermittently. ``` ruby # repro.rb require 'open3' class ProcessWrapper def initialize @stdin, @stdout, @stderr, @wait_thread = Open3.popen3("cat") ObjectSpace.define_finalizer(self, self.class.make_finalizer(@stdin, @stdout, @stderr, @wait_thread)) end def self.make_finalizer(stdin, stdout, stderr, wait_thread) proc do stdin.close rescue nil stdout.close rescue nil stderr.close rescue nil wait_thread.value # Hangs here in Ruby 3.3+ end end end 100.times { ProcessWrapper.new } GC.stress = true 1000.times { Object.new } puts "done" ``` ## Environment - Linux x86_64 - Tested on Ruby 3.2.7, 3.3.7, 3.4.8 -- https://bugs.ruby-lang.org/