https://github.com/python/cpython/commit/353e6d3eff1172bd7df9340436b55a505f850a06
commit: 353e6d3eff1172bd7df9340436b55a505f850a06
branch: main
author: Timofei Ivankov <[email protected]>
committer: kumaraditya303 <[email protected]>
date: 2026-07-28T06:59:49Z
summary:
gh-150866: Fix asyncio shutdown_asyncgens to report BaseException (#150867)
files:
A Misc/NEWS.d/next/Library/2026-06-03-18-41-42.gh-issue-150866.gXGyX-.rst
M Lib/asyncio/base_events.py
M Lib/test/test_asyncio/test_base_events.py
diff --git a/Lib/asyncio/base_events.py b/Lib/asyncio/base_events.py
index 3836aaad326f62e..f26fba175b63cd7 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, BaseException):
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 1622f19f0213f3c..18afdca23163a1e 100644
--- a/Lib/test/test_asyncio/test_base_events.py
+++ b/Lib/test/test_asyncio/test_base_events.py
@@ -1042,6 +1042,60 @@ async def iter_one():
asyncio.create_task(iter_one())
return status
+ def test_shutdown_asyncgens_reports_base_exceptions(self):
+ # gh-150866: shutdown_asyncgens silently swallowed exceptions that
+ # don't inherit from Exception 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()
+
+ class MyBaseException(BaseException):
+ pass
+
+ async def agen_cancel():
+ try:
+ yield 1
+ finally:
+ raise asyncio.CancelledError("agen got cancelled during
cleanup")
+
+ async def agen_base():
+ try:
+ yield 1
+ finally:
+ raise MyBaseException("base exc 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['exception'])
+
+ async def main():
+ loop = asyncio.get_running_loop()
+ loop.set_exception_handler(handler)
+
+ g1 = agen_cancel()
+ g2 = agen_base()
+ g3 = agen_value_error()
+ await g1.__anext__()
+ await g2.__anext__()
+ await g3.__anext__()
+
+ await loop.shutdown_asyncgens()
+
+ self.loop.run_until_complete(main())
+ self.assertEqual(len(caught), 3)
+ self.assertEqual(
+ {type(exc) for exc in caught},
+ {asyncio.CancelledError, MyBaseException, ValueError},
+ )
+
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..57af6e954384b10
--- /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 any
+:exc:`BaseException` raised during asynchronous generator cleanup.
_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]