gh-113538: Don't error in stream reader protocol callback when task is cancelled (#113690)

This commit is contained in:
Guido van Rossum 2024-01-04 12:20:21 -08:00 committed by GitHub
parent 1600d78e2d
commit 4681a5271a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 21 additions and 7 deletions

View file

@ -246,6 +246,9 @@ def connection_made(self, transport):
self._stream_writer)
if coroutines.iscoroutine(res):
def callback(task):
if task.cancelled():
transport.close()
return
exc = task.exception()
if exc is not None:
self._loop.call_exception_handler({

View file

@ -1129,7 +1129,7 @@ async def inner(httpd):
self.assertEqual(messages, [])
def test_unhandled_exceptions(self) -> None:
def _basetest_unhandled_exceptions(self, handle_echo):
port = socket_helper.find_unused_port()
messages = []
@ -1143,9 +1143,6 @@ async def client():
await wr.wait_closed()
async def main():
async def handle_echo(reader, writer):
raise Exception('test')
server = await asyncio.start_server(
handle_echo, 'localhost', port)
await server.start_serving()
@ -1154,11 +1151,20 @@ async def handle_echo(reader, writer):
await server.wait_closed()
self.loop.run_until_complete(main())
return messages
def test_unhandled_exception(self):
async def handle_echo(reader, writer):
raise Exception('test')
messages = self._basetest_unhandled_exceptions(handle_echo)
self.assertEqual(messages[0]['message'],
'Unhandled exception in client_connected_cb')
# Break explicitly reference cycle
messages = None
'Unhandled exception in client_connected_cb')
def test_unhandled_cancel(self):
async def handle_echo(reader, writer):
asyncio.current_task().cancel()
messages = self._basetest_unhandled_exceptions(handle_echo)
self.assertEqual(messages, [])
if __name__ == '__main__':

View file

@ -0,0 +1,5 @@
In :meth:`asyncio.StreamReaderProtocol.connection_made`, there is callback
that logs an error if the task wrapping the "connected callback" fails. This
callback would itself fail if the task was cancelled. Prevent this by
checking whether the task was cancelled first. If so, close the transport
but don't log an error.