Description
When WEBrick shutdowns, it tries to concurrently write and close a file descriptor, and even tries to close it from multiple threads:
closing it from the main webrick thread:
Line 207 in 841b7da
closing it from an arbitrary thread:
Line 237 in 841b7da
writing to it (from an arbitrary thread):
Line 227 in 841b7da
A hack:
Line 353 in 841b7da
The problem is if the write_nonblock
which calls write(2) ends up happening once the fd
is close(2)d then it's EBADF, or worse writing to the wrong file descriptor.
This became such an issue that ruby/spec stopped using WEBrick and rewrote to make its own HTTP server to avoid this issue. Also the commit message of ruby/spec@d8ead5d may be interesting.
Only one thread (e.g. the main webrick thread) should close it, and it should wait all sub-threads before closing it so there are concurrent writes to the close.
CRuby has some very complex logic in IO#close which avoids the issue in most cases but it's not clear if it's fully reliable: https://ruby.slack.com/archives/C02A3SL0S/p1636604027275700?thread_ts=1636592668.266300&cid=C02A3SL0S
IIRC I've seen it fail for ruby/spec too on CRuby.
cc @ioquatix