Skip to content

Commit 92ba4e1

Browse files
[3.12] gh-113538: Don't error in stream reader protocol callback when task is cancelled (GH-113690) (#113713)
(cherry picked from commit 4681a52) Co-authored-by: Guido van Rossum <guido@python.org>
1 parent d3f2051 commit 92ba4e1

File tree

3 files changed

+21
-7
lines changed

3 files changed

+21
-7
lines changed

Lib/asyncio/streams.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,9 @@ def connection_made(self, transport):
246246
self._stream_writer)
247247
if coroutines.iscoroutine(res):
248248
def callback(task):
249+
if task.cancelled():
250+
transport.close()
251+
return
249252
exc = task.exception()
250253
if exc is not None:
251254
self._loop.call_exception_handler({

Lib/test/test_asyncio/test_streams.py

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1129,7 +1129,7 @@ async def inner(httpd):
11291129

11301130
self.assertEqual(messages, [])
11311131

1132-
def test_unhandled_exceptions(self) -> None:
1132+
def _basetest_unhandled_exceptions(self, handle_echo):
11331133
port = socket_helper.find_unused_port()
11341134

11351135
messages = []
@@ -1143,9 +1143,6 @@ async def client():
11431143
await wr.wait_closed()
11441144

11451145
async def main():
1146-
async def handle_echo(reader, writer):
1147-
raise Exception('test')
1148-
11491146
server = await asyncio.start_server(
11501147
handle_echo, 'localhost', port)
11511148
await server.start_serving()
@@ -1154,11 +1151,20 @@ async def handle_echo(reader, writer):
11541151
await server.wait_closed()
11551152

11561153
self.loop.run_until_complete(main())
1154+
return messages
11571155

1156+
def test_unhandled_exception(self):
1157+
async def handle_echo(reader, writer):
1158+
raise Exception('test')
1159+
messages = self._basetest_unhandled_exceptions(handle_echo)
11581160
self.assertEqual(messages[0]['message'],
1159-
'Unhandled exception in client_connected_cb')
1160-
# Break explicitly reference cycle
1161-
messages = None
1161+
'Unhandled exception in client_connected_cb')
1162+
1163+
def test_unhandled_cancel(self):
1164+
async def handle_echo(reader, writer):
1165+
asyncio.current_task().cancel()
1166+
messages = self._basetest_unhandled_exceptions(handle_echo)
1167+
self.assertEqual(messages, [])
11621168

11631169

11641170
if __name__ == '__main__':
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
In :meth:`asyncio.StreamReaderProtocol.connection_made`, there is callback
2+
that logs an error if the task wrapping the "connected callback" fails. This
3+
callback would itself fail if the task was cancelled. Prevent this by
4+
checking whether the task was cancelled first. If so, close the transport
5+
but don't log an error.

0 commit comments

Comments
 (0)