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

(cherry picked from commit 4681a5271a8598b46021cbc556ac8098ab8a1d81)

Co-authored-by: Guido van Rossum <guido@python.org>
This commit is contained in:
Miss Islington (bot) 2024-01-04 21:39:52 +01:00 committed by GitHub
parent c828dbc196
commit 456e2ecdd2
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 @@ class StreamReaderProtocol(FlowControlMixin, protocols.Protocol):
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

@ -1123,7 +1123,7 @@ os.close(fd)
self.assertEqual(messages, [])
def test_unhandled_exceptions(self) -> None:
def _basetest_unhandled_exceptions(self, handle_echo):
port = socket_helper.find_unused_port()
messages = []
@ -1137,9 +1137,6 @@ os.close(fd)
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()
@ -1148,11 +1145,20 @@ os.close(fd)
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.