From 5181170c3516a4190ccce65d29342999f5b89beb Mon Sep 17 00:00:00 2001 From: Timofey Ivankov Date: Wed, 15 Jul 2026 14:30:16 +0300 Subject: [PATCH 1/2] gh-153761: Fix asyncio sock_accept() dropping a connection when cancelled --- Lib/asyncio/selector_events.py | 3 ++ Lib/test/test_asyncio/test_sock_lowlevel.py | 43 +++++++++++++++++++ ...-07-15-14-24-18.gh-issue-153761.8jqs67.rst | 2 + 3 files changed, 48 insertions(+) create mode 100644 Misc/NEWS.d/next/Library/2026-07-15-14-24-18.gh-issue-153761.8jqs67.rst diff --git a/Lib/asyncio/selector_events.py b/Lib/asyncio/selector_events.py index 492dfcb19dafe2..da3735390df177 100644 --- a/Lib/asyncio/selector_events.py +++ b/Lib/asyncio/selector_events.py @@ -718,6 +718,9 @@ async def sock_accept(self, sock): return await fut def _sock_accept(self, fut, sock): + # gh-153761: _sock_accept must not scheduled with already cancelled future + if fut.done(): + return fd = sock.fileno() try: conn, address = sock.accept() diff --git a/Lib/test/test_asyncio/test_sock_lowlevel.py b/Lib/test/test_asyncio/test_sock_lowlevel.py index 5d825440e41ca7..c68211968a80d8 100644 --- a/Lib/test/test_asyncio/test_sock_lowlevel.py +++ b/Lib/test/test_asyncio/test_sock_lowlevel.py @@ -1,5 +1,6 @@ import socket import asyncio +import select import sys import unittest @@ -257,6 +258,38 @@ async def _basetest_sock_connect_racing(self, listener, sock): self.skipTest(skip_reason) + async def _basetest_sock_accept_racing(self, listener, sock): + # gh-153761: cancelling sock_accept() must not let a scheduled + # _sock_accept run on the cancelled future. + listener.setblocking(False) + listener.bind(('127.0.0.1', 0)) + listener.listen(1) + addr = listener.getsockname() + + errors = [] + self.loop.set_exception_handler(lambda loop, ctx: errors.append(ctx)) + task = asyncio.create_task(self.loop.sock_accept(listener)) + await asyncio.sleep(0) + + sock.connect(addr) + select.select([listener], [], [], support.SHORT_TIMEOUT) + + self.loop.call_soon(task.cancel) + await asyncio.sleep(0) + await asyncio.sleep(0) + + with self.assertRaises(asyncio.CancelledError): + await task + self.assertEqual(errors, []) + + # The pending connection must survive + conn, conn_addr = await self.loop.sock_accept(listener) + with conn: + self.assertEqual(conn_addr, sock.getsockname()) + sock.setblocking(False) + await self.loop.sock_sendall(conn, b'ping') + self.assertEqual(await self.loop.sock_recv(sock, 4), b'ping') + def test_sock_client_racing(self): with test_utils.run_test_server() as httpd: sock = socket.socket() @@ -280,6 +313,16 @@ def test_sock_client_connect_racing(self): self.loop.run_until_complete(asyncio.wait_for( self._basetest_sock_connect_racing(listener, sock), 10)) + def test_sock_accept_racing(self): + if sys.platform == 'win32': + if isinstance(self.loop, asyncio.ProactorEventLoop): + raise unittest.SkipTest('Not relevant to ProactorEventLoop') + listener = socket.socket() + sock = socket.socket() + with listener, sock: + self.loop.run_until_complete(asyncio.wait_for( + self._basetest_sock_accept_racing(listener, sock), 10)) + async def _basetest_huge_content(self, address): sock = socket.socket() sock.setblocking(False) diff --git a/Misc/NEWS.d/next/Library/2026-07-15-14-24-18.gh-issue-153761.8jqs67.rst b/Misc/NEWS.d/next/Library/2026-07-15-14-24-18.gh-issue-153761.8jqs67.rst new file mode 100644 index 00000000000000..d64f8de1aaf3c3 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-07-15-14-24-18.gh-issue-153761.8jqs67.rst @@ -0,0 +1,2 @@ +Fix cancelling :meth:`asyncio.BaseSelectorEventLoop._sock_accept` dropping a pending +connection. From 4692278aae1994f35fa157dd0a296c17a58ade43 Mon Sep 17 00:00:00 2001 From: Timofey Ivankov Date: Wed, 15 Jul 2026 14:49:59 +0300 Subject: [PATCH 2/2] fix NEWS entry link --- .../Library/2026-07-15-14-24-18.gh-issue-153761.8jqs67.rst | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Misc/NEWS.d/next/Library/2026-07-15-14-24-18.gh-issue-153761.8jqs67.rst b/Misc/NEWS.d/next/Library/2026-07-15-14-24-18.gh-issue-153761.8jqs67.rst index d64f8de1aaf3c3..68e007e66e0396 100644 --- a/Misc/NEWS.d/next/Library/2026-07-15-14-24-18.gh-issue-153761.8jqs67.rst +++ b/Misc/NEWS.d/next/Library/2026-07-15-14-24-18.gh-issue-153761.8jqs67.rst @@ -1,2 +1 @@ -Fix cancelling :meth:`asyncio.BaseSelectorEventLoop._sock_accept` dropping a pending -connection. +Fix cancelling :meth:`asyncio.loop.sock_accept` dropping a pending connection.