Skip to content

Commit 52b7dd7

Browse files
committed
gh-150866: Fix asyncio.shutdown_asyncgens to report CancelledError
1 parent 32104a1 commit 52b7dd7

3 files changed

Lines changed: 42 additions & 1 deletion

File tree

Lib/asyncio/base_events.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -590,7 +590,7 @@ async def shutdown_asyncgens(self):
590590
return_exceptions=True)
591591

592592
for result, agen in zip(results, closing_agens):
593-
if isinstance(result, Exception):
593+
if isinstance(result, (Exception, exceptions.CancelledError)):
594594
self.call_exception_handler({
595595
'message': f'an error occurred during closing of '
596596
f'asynchronous generator {agen!r}',

Lib/test/test_asyncio/test_base_events.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1041,6 +1041,45 @@ async def iter_one():
10411041

10421042
asyncio.create_task(iter_one())
10431043
return status
1044+
1045+
def test_shutdown_asyncgens_reports_cancelled_error(self):
1046+
# gh-150866: shutdown_asyncgens silently swallowed
1047+
# CancelledError raised during aclose() because the check was
1048+
# isinstance(result, Exception), but CancelledError inherits
1049+
# from BaseException.
1050+
self.loop._process_events = mock.Mock()
1051+
self.loop._write_to_self = mock.Mock()
1052+
1053+
async def agen_cancel():
1054+
try:
1055+
yield 1
1056+
finally:
1057+
raise asyncio.CancelledError("agen got cancelled during cleanup")
1058+
1059+
async def agen_value_error():
1060+
try:
1061+
yield 1
1062+
finally:
1063+
raise ValueError("agen failed during cleanup")
1064+
1065+
caught = []
1066+
1067+
def handler(loop, context):
1068+
caught.append(context['message'])
1069+
1070+
async def main():
1071+
loop = asyncio.get_running_loop()
1072+
loop.set_exception_handler(handler)
1073+
1074+
g1 = agen_cancel()
1075+
g2 = agen_value_error()
1076+
await g1.__anext__()
1077+
await g2.__anext__()
1078+
1079+
await loop.shutdown_asyncgens()
1080+
1081+
self.loop.run_until_complete(main())
1082+
self.assertEqual(len(caught), 2)
10441083

10451084
def test_asyncgen_finalization_by_gc(self):
10461085
# Async generators should be finalized when garbage collected.
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fix :meth:`asyncio.loop.shutdown_asyncgens` to report
2+
:exc:`asyncio.CancelledError` raised during asynchronous generator cleanup.

0 commit comments

Comments
 (0)