diff --git a/Lib/asyncio/base_events.py b/Lib/asyncio/base_events.py index 1fedb066f94c539..928f313aafe07af 100644 --- a/Lib/asyncio/base_events.py +++ b/Lib/asyncio/base_events.py @@ -590,7 +590,7 @@ async def shutdown_asyncgens(self): return_exceptions=True) for result, agen in zip(results, closing_agens): - if isinstance(result, Exception): + if isinstance(result, (Exception, exceptions.CancelledError)): self.call_exception_handler({ 'message': f'an error occurred during closing of ' f'asynchronous generator {agen!r}', diff --git a/Lib/test/test_asyncio/test_base_events.py b/Lib/test/test_asyncio/test_base_events.py index e59bc25668b4cba..d6642728acb08db 100644 --- a/Lib/test/test_asyncio/test_base_events.py +++ b/Lib/test/test_asyncio/test_base_events.py @@ -1042,6 +1042,45 @@ async def iter_one(): asyncio.create_task(iter_one()) return status + def test_shutdown_asyncgens_reports_cancelled_error(self): + # gh-150866: shutdown_asyncgens silently swallowed + # CancelledError raised during aclose() because the check was + # isinstance(result, Exception), but CancelledError inherits + # from BaseException. + self.loop._process_events = mock.Mock() + self.loop._write_to_self = mock.Mock() + + async def agen_cancel(): + try: + yield 1 + finally: + raise asyncio.CancelledError("agen got cancelled during cleanup") + + async def agen_value_error(): + try: + yield 1 + finally: + raise ValueError("agen failed during cleanup") + + caught = [] + + def handler(loop, context): + caught.append(context['message']) + + async def main(): + loop = asyncio.get_running_loop() + loop.set_exception_handler(handler) + + g1 = agen_cancel() + g2 = agen_value_error() + await g1.__anext__() + await g2.__anext__() + + await loop.shutdown_asyncgens() + + self.loop.run_until_complete(main()) + self.assertEqual(len(caught), 2) + def test_asyncgen_finalization_by_gc(self): # Async generators should be finalized when garbage collected. self.loop._process_events = mock.Mock() diff --git a/Misc/NEWS.d/next/Library/2026-06-03-18-41-42.gh-issue-150866.gXGyX-.rst b/Misc/NEWS.d/next/Library/2026-06-03-18-41-42.gh-issue-150866.gXGyX-.rst new file mode 100644 index 000000000000000..60e792b70a00d5a --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-06-03-18-41-42.gh-issue-150866.gXGyX-.rst @@ -0,0 +1,2 @@ +Fix :meth:`asyncio.loop.shutdown_asyncgens` to report +:exc:`asyncio.CancelledError` raised during asynchronous generator cleanup.