Skip to content

Commit ca2ee21

Browse files
committed
respond to code review comments
1 parent eb09595 commit ca2ee21

3 files changed

Lines changed: 15 additions & 31 deletions

File tree

Lib/asyncio/proactor_events.py

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -574,11 +574,9 @@ def _loop_reading(self, fut=None):
574574
except OSError as exc:
575575
self._protocol.error_received(exc)
576576
if not self._closing and not self._conn_lost:
577-
# Some errors are transient and recoverable, e.g. a
578-
# ConnectionResetError raised synchronously by WSARecvFrom()
579-
# from a stale ICMP port-unreachable notification on a UDP
580-
# socket. Re-arm the read loop instead of leaving it dead
581-
# (gh-127057).
577+
# The error can be transient, e.g. a ConnectionResetError
578+
# from a stale ICMP port unreachable notification, so
579+
# re-arm the read loop instead of leaving it dead.
582580
self._loop.call_soon(self._loop_reading)
583581
except exceptions.CancelledError:
584582
if not self._closing:

Lib/test/test_asyncio/test_events.py

Lines changed: 9 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1584,14 +1584,9 @@ def create_socket():
15841584
transport_2.close()
15851585

15861586
def test_datagram_recvfrom_connection_reset_recovers(self):
1587-
# gh-127057: on Windows, a UDP socket that previously sent a
1588-
# datagram to an address that wasn't listening can raise
1589-
# ConnectionResetError (WSAECONNRESET) on a later receive
1590-
# attempt: synchronously from WSARecvFrom() on ProactorEventLoop
1591-
# (instead of via the completion result already handled in
1592-
# _finish_recvfrom() for gh-91227), or from a plain recvfrom()
1593-
# on SelectorEventLoop. Either way the transport must keep
1594-
# working afterwards instead of the read loop dying silently.
1587+
# gh-127057: a UDP socket that sent a datagram to an address that
1588+
# wasn't listening can raise ConnectionResetError on a later
1589+
# receive. The transport must keep working afterwards.
15951590
loop = self.loop
15961591

15971592
class Protocol(asyncio.DatagramProtocol):
@@ -1621,27 +1616,21 @@ def datagram_received(self, data, addr):
16211616
closed_addr = closed.getsockname()
16221617
closed.close()
16231618

1624-
# Trigger a real ICMP port-unreachable now, before the socket is
1625-
# wrapped in a transport and before any read is armed for it --
1626-
# on Windows this is what makes a Proactor's first WSARecvFrom()
1627-
# call raise synchronously.
1619+
# Trigger the error before the socket is wrapped in a transport,
1620+
# so that the first read raises synchronously.
16281621
sock.sendto(b'x', closed_addr)
16291622

16301623
transport, protocol = loop.run_until_complete(
16311624
loop.create_datagram_endpoint(Protocol, sock=sock))
16321625

1633-
# The transport must still be able to receive afterwards -- this
1634-
# is the actual regression check, and must hold regardless of
1635-
# whether this platform surfaced an error for the bad send above.
16361626
transport.sendto(b'ping', addr)
1637-
loop.run_until_complete(
1638-
asyncio.wait_for(protocol.datagram_received_event, 10))
1627+
loop.run_until_complete(asyncio.wait_for(
1628+
protocol.datagram_received_event, support.SHORT_TIMEOUT))
16391629
self.assertEqual(protocol.received, [b'ping'])
16401630

16411631
if sys.platform == 'win32':
1642-
# Windows reliably reports the bad send via a later recvfrom();
1643-
# other platforms generally don't deliver ICMP errors to a
1644-
# plain recv() on an unconnected UDP socket.
1632+
# Other platforms don't report ICMP errors on an
1633+
# unconnected UDP socket.
16451634
self.assertEqual(len(protocol.errors), 1)
16461635
self.assertIsInstance(protocol.errors[0], ConnectionResetError)
16471636

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,3 @@
1-
Fix :class:`asyncio.ProactorEventLoop` UDP transports so a
2-
:exc:`ConnectionResetError` raised synchronously from ``WSARecvFrom``
3-
(reported when the same socket was previously used to send to an
4-
address that isn't listening) no longer breaks the read loop. This
5-
complements the existing handling of the equivalent asynchronous
6-
``ERROR_PORT_UNREACHABLE`` completion result.
1+
Fix :class:`asyncio.ProactorEventLoop` UDP transports so that a
2+
:exc:`ConnectionResetError` raised by ``WSARecvFrom`` no longer stops the
3+
read loop.

0 commit comments

Comments
 (0)