Closed damz closed 6 years ago
(The advantage for waiting for Go 1.11 is that deadlines will work out of the box too.)
I implemented the Go 1.11+ option in a3be7e1e8842c1b48fbe5388137762e50913c029, and it works beautifully.
Very interesting. So if I understand correctly we will get timeouts and everything for free with Go 1.11 too? That's been one of my biggest gripes with nonstandard socket types for years.
Once 1.11 lands I have no qualms making changes and requiring 1.11 to build this package. In the mean time, it'd probably be good to do the workaround you suggested for 1.10 and below.
@mdlayher Yes, with Go 1.11 and the patch in a3be7e1e8842c1b48fbe5388137762e50913c029 you get for free:
Close
unblocks Read
and Write
semantics;SetDeadline
, SetReadDeadline
and SetWriteDeadline
).Thanks again for the report. We hit this issue in production and I made a comparable patch to solve the issue. Closing this issue now as it appears to be fixed.
This is a pretty big and unexpected departure from the
net.Conn
contract, which explicitly states:The reason it happens is that in current versions of Go,
os.NewFile()
assumes that the provided file descriptor points to a file and doesn't support polling. As a consequence, it uses straight syscalls to handleRead
andWrite
, and it is a well known weirdness of Linux thatclose()
doesn't unblockrecv*()
from other threads. From theclose(2)
manpage:From there, there are two options:
Close()
to callshutdown()
, which will unblock the blockedrecv()
;os.File
objects fromos.NewFile()
. For that, all you have to do is to set the file descriptor to non-blocking mode before passing it toos.NewFile()