Bug report
Bug description:
asyncio.BaseEventLoop.shutdown_asyncgens silently swallows CancelledError raised during asynchronous generator cleanup:
# Lib/asyncio/base_events.py:592-599
for result, agen in zip(results, closing_agens):
if isinstance(result, Exception):
self.call_exception_handler({
'message': f'an error occurred during closing of '
f'asynchronous generator {agen!r}',
'exception': result,
'asyncgen': agen
})
CancelledError that can be raised by the aclose() is not inherited from the Exception, it inherits from BaseException.
Reproducer:
import asyncio
async def agen():
try:
yield 1
finally:
raise asyncio.CancelledError("cancelled during cleanup")
caught = []
async def main():
loop = asyncio.get_running_loop()
loop.set_exception_handler(lambda loop, ctx: caught.append(ctx))
g = agen()
await g.__anext__()
await loop.shutdown_asyncgens()
asyncio.run(main())
assert len(caught) == 1, f"Expected 1 handler call, got {len(caught)}"
Proposed fix:
Match both Exception and CancelledError
if isinstance(result, (Exception, asyncio.CancelledError)):
CPython versions tested on:
3.16, CPython main branch
Operating systems tested on:
macOS
Linked PRs
Bug report
Bug description:
asyncio.BaseEventLoop.shutdown_asyncgenssilently swallowsCancelledErrorraised during asynchronous generator cleanup:CancelledErrorthat can be raised by theaclose()is not inherited from theException, it inherits fromBaseException.Reproducer:
Proposed fix:
Match both Exception and CancelledError
CPython versions tested on:
3.16, CPython main branch
Operating systems tested on:
macOS
Linked PRs