Fixed socket aclose() delayed close, missing checkpoint and Windows hang - #1289
Fixed socket aclose() delayed close, missing checkpoint and Windows hang#1289graingert wants to merge 3 commits into
Conversation
On the asyncio backend, SocketStream, UDPSocket and ConnectedUDPSocket closed through transport.close(), which only schedules the FD-closing connection_lost callback via loop.call_soon. A second, concurrent aclose() -- as aclose_forcefully() can produce -- therefore returned while the socket was still open, and on Windows closing a UDP socket with a datagram still in flight could hang outright. All three now abort() the transport directly, which also makes DatagramProtocol.closed_event unnecessary. None of the implementations checkpointed either, so aclose() called inside an already-cancelled scope returned normally instead of raising a cancellation exception. This affected UNIX socket streams and UNIX datagram sockets on asyncio, and every socket type on Trio. _RawSocketMixin.aclose() now always closes the raw socket and checkpoints, while still resolving pending receive and send futures only on the first call, so a task blocked in receive() or send() is woken exactly once. Fixes agronholm#1237. Fixes agronholm#1273. Fixes agronholm#1288.
3369660 to
5149806
Compare
|
Does this obsolete #1273? |
|
No it fixes it, #1273 is an issue, did you mean to reference a PR? |
|
Sorry, I'm juggling a number of related PRs and issues in the milestone. |
|
So, my first thought here was that we checkpoint in |
|
see https://trio.readthedocs.io/en/stable/reference-core.html#cancellation-and-primitive-operations
|
|
I have concerns about the |
|
Because we call |
NOTE Erasing or replacing the contents of this template will result in your pull
request being summarily closed without consideration!
Changes
Fixes #1237. Fixes #1273. Fixes #1288.
Socket
aclose()implementations had three related problems.On the asyncio backend,
SocketStream,UDPSocketandConnectedUDPSocketclosedthrough
transport.close(), which only schedules the FD-closingconnection_lostcallback via
loop.call_soon. A second, concurrentaclose()— asaclose_forcefully()can produce — therefore returned while the socket was still open,and on Windows closing a UDP socket with a datagram still in flight could hang outright.
All three now
abort()the transport directly, which also makesDatagramProtocol.closed_eventunnecessary.None of the implementations checkpointed either, so
aclose()called inside analready-cancelled scope returned normally instead of raising a cancellation exception.
This affected UNIX socket streams and UNIX datagram sockets on asyncio, and every socket
type on Trio.
_RawSocketMixin.aclose()now always closes the raw socket and checkpoints, while stillresolving pending receive and send futures only on the first call, so a task blocked in
receive()orsend()is woken exactly once.Checklist
If this is a user-facing code change, like a bugfix or a new feature, please ensure that
you've fulfilled the following conditions (where applicable):
tests/) which would fail without your patchdocs/), in case of behavior changes or newfeatures
docs/versionhistory.rst).If this is a trivial change, like a typo fix or a code reformatting, then you can ignore
these instructions.