Project

General

Profile

Bug #22456 » repro.rb

txapelgorri (Ibon Castilla), 10/19/2026 03:08 PM

 
# IO#close hangs forever when the thread writing to that IO is running a trap handler.
# Usage: ruby repro.rb [trap|thread]
mode = ARGV[0] || "trap"

r, w = IO.pipe
begin
loop { w.write_nonblock("x" * 4096) } # fill the pipe so the next write blocks
rescue IO::WaitWritable
end

closer = nil
write = lambda do
closer = Thread.new { sleep 0.3; w.close; :closed } # close while the other thread is blocked writing
begin
w.syswrite("y")
puts "write: returned"
rescue Exception => e
puts "write: #{e.class}: #{e.message}"
end
end

if mode == "trap"
Signal.trap("USR1") { write.call }
Process.kill("USR1", Process.pid)
sleep 0.1 until closer
else
write.call
end

result = closer.join(3)
puts "#{RUBY_DESCRIPTION}, #{mode}: " +
(result ? "IO#close returned" : "IO#close HANGS (#{closer.status}) at #{closer.backtrace&.first}")
(2-2/2)