mirror of
https://github.com/python/cpython.git
synced 2025-11-01 14:11:41 +00:00
bpo-41317: Remove reader on cancellation in asyncio.loop.sock_accept() (GH-21595)
(cherry picked from commit 0dd98c2d00)
Co-authored-by: Alex Grönholm <alex.gronholm@nextday.fi>
This commit is contained in:
parent
e8dda907fb
commit
4ff8e5ba4f
3 changed files with 27 additions and 7 deletions
|
|
@ -555,20 +555,19 @@ async def sock_accept(self, sock):
|
||||||
if self._debug and sock.gettimeout() != 0:
|
if self._debug and sock.gettimeout() != 0:
|
||||||
raise ValueError("the socket must be non-blocking")
|
raise ValueError("the socket must be non-blocking")
|
||||||
fut = self.create_future()
|
fut = self.create_future()
|
||||||
self._sock_accept(fut, False, sock)
|
self._sock_accept(fut, sock)
|
||||||
return await fut
|
return await fut
|
||||||
|
|
||||||
def _sock_accept(self, fut, registered, sock):
|
def _sock_accept(self, fut, sock):
|
||||||
fd = sock.fileno()
|
fd = sock.fileno()
|
||||||
if registered:
|
|
||||||
self.remove_reader(fd)
|
|
||||||
if fut.done():
|
|
||||||
return
|
|
||||||
try:
|
try:
|
||||||
conn, address = sock.accept()
|
conn, address = sock.accept()
|
||||||
conn.setblocking(False)
|
conn.setblocking(False)
|
||||||
except (BlockingIOError, InterruptedError):
|
except (BlockingIOError, InterruptedError):
|
||||||
self.add_reader(fd, self._sock_accept, fut, True, sock)
|
self._ensure_fd_no_transport(fd)
|
||||||
|
handle = self._add_reader(fd, self._sock_accept, fut, sock)
|
||||||
|
fut.add_done_callback(
|
||||||
|
functools.partial(self._sock_read_done, fd, handle=handle))
|
||||||
except (SystemExit, KeyboardInterrupt):
|
except (SystemExit, KeyboardInterrupt):
|
||||||
raise
|
raise
|
||||||
except BaseException as exc:
|
except BaseException as exc:
|
||||||
|
|
|
||||||
|
|
@ -415,6 +415,25 @@ def test_sock_accept(self):
|
||||||
conn.close()
|
conn.close()
|
||||||
listener.close()
|
listener.close()
|
||||||
|
|
||||||
|
def test_cancel_sock_accept(self):
|
||||||
|
listener = socket.socket()
|
||||||
|
listener.setblocking(False)
|
||||||
|
listener.bind(('127.0.0.1', 0))
|
||||||
|
listener.listen(1)
|
||||||
|
sockaddr = listener.getsockname()
|
||||||
|
f = asyncio.wait_for(self.loop.sock_accept(listener), 0.1)
|
||||||
|
with self.assertRaises(asyncio.TimeoutError):
|
||||||
|
self.loop.run_until_complete(f)
|
||||||
|
|
||||||
|
listener.close()
|
||||||
|
client = socket.socket()
|
||||||
|
client.setblocking(False)
|
||||||
|
f = self.loop.sock_connect(client, sockaddr)
|
||||||
|
with self.assertRaises(ConnectionRefusedError):
|
||||||
|
self.loop.run_until_complete(f)
|
||||||
|
|
||||||
|
client.close()
|
||||||
|
|
||||||
def test_create_connection_sock(self):
|
def test_create_connection_sock(self):
|
||||||
with test_utils.run_test_server() as httpd:
|
with test_utils.run_test_server() as httpd:
|
||||||
sock = None
|
sock = None
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
Use add_done_callback() in asyncio.loop.sock_accept() to unsubscribe reader
|
||||||
|
early on cancellation.
|
||||||
Loading…
Add table
Add a link
Reference in a new issue