From: Tanaka Akira Date: 2010-07-06T12:39:30+09:00 Subject: [ruby-core:31065] Re: [Bug #3540] IO.copy_stream fails to detect client disconnect w/sendfile 2010/7/6 Eric Wong : > > sendfile() may return with a short write upon a client disconnect. Instead of > retrying and getting an error, Ruby tries to force a select() on the descriptor > which fails to detect the disconnect. This causes IO.copy_stream to hang, > (possibly until TCP keepalives kick in). IO.copy_stream should raise > immediately. Thank you for the reproducible script and fix. I'll commit your fix. However I think the Linux select behavior which doesn't notify writability on disconnected TCP socket is suspicious. linux% ruby -rsocket -e ' serv = TCPServer.open("127.0.0.1", 8888) s1 = TCPSocket.open("127.0.0.1", 8888) s2 = serv.accept s2.close s1.write "a" rescue p $! s1.write "a" rescue p $! p IO.select(nil, [s1], nil, 0) ' # nil FreeBSD and Solaris notify writability. freebsd% ruby -rsocket -e ' serv = TCPServer.open("127.0.0.1", 8888) s1 = TCPSocket.open("127.0.0.1", 8888) s2 = serv.accept s2.close s1.write "a" rescue p $! s1.write "a" rescue p $! p IO.select(nil, [s1], nil, 0) ' # [[], [#], []] solaris% ruby -rsocket -e ' serv = TCPServer.open("127.0.0.1", 8888) s1 = TCPSocket.open("127.0.0.1", 8888) s2 = serv.accept s2.close s1.write "a" rescue p $! s1.write "a" rescue p $! p IO.select(nil, [s1], nil, 0) ' # [[], [#], []] I think select should notify writability when write would not block. Cleary write doesn't block on disconnected socket. Linux also notify writability for UNIX domain socket pair. linux% ruby -rsocket -e ' s1, s2 = UNIXSocket.pair s2.close s1.write "a" rescue p $! p IO.select(nil, [s1], nil, 0) ' # [[], [#], []] I tested Linux 2.6.26. -- Tanaka Akira