[ruby-core:108223] [Ruby master Misc#18725] IO#write and IO#wait_writable block for write pipe if read pipe is closed in other thread on OpenBSD
From:
"jeremyevans0 (Jeremy Evans)" <noreply@...>
Date:
2022-04-13 23:20:53 UTC
List:
ruby-core #108223
Issue #18725 has been reported by jeremyevans0 (Jeremy Evans).
----------------------------------------
Misc #18725: IO#write and IO#wait_writable block for write pipe if read pipe is closed in other thread on OpenBSD
https://bugs.ruby-lang.org/issues/18725
* Author: jeremyevans0 (Jeremy Evans)
* Status: Open
* Priority: Normal
----------------------------------------
I'm not sure whether this is a Ruby issue, an OpenBSD issue, or something else, but @ioquatix asked me to post this here. The following program hangs on OpenBSD:
```ruby
require 'io/wait'
rd, wr = IO.pipe
thread_pass = ARGV[0] == 'pass'
write = ARGV[0] == 'write'
thread = Thread.new do
longer = "0" * 1024 * 1024
(1024 * 4).times do
if write
wr.write(longer)
else
while wr.write_nonblock(longer, :exception=>false) == :wait_writable
thread_pass ? Thread.pass : wr.wait_writable
end
end
end
:finished
rescue => e
e
end
sleep 1
rd.close
puts :rd_close
puts thread.value
```
This program will also hang if `write` is given as the argument, using `wr.write` instead of `wr.write_nonblock`/`wr.wait_writable`. However, if `pass` is given as the argument, using `Thread.pass` instead of `wr.wait_writable`, the program will not hang.
From testing, the hang when called without an argument is in `wait_writable`, and the hang with a `write` argument is in `write`.
Is Ruby supposed to guarantee that a closing the read end of a pipe in one thread causes a raise of EPIPE to the write end of the pipe in a different thread if already inside `IO#write`/`IO#wait_writable`? Or is this platform-specific behavior?
This example was extracted from one of Rack's tests, which was causing non-deterministic hangs on OpenBSD.
--
https://bugs.ruby-lang.org/
Unsubscribe: <mailto:ruby-core-request@ruby-lang.org?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-core>