From 3b776cf15a585e0d2ec32e7847072ed753c964d5 Mon Sep 17 00:00:00 2001 From: Timofey Ivankov Date: Sun, 9 Aug 2026 16:15:52 +0300 Subject: [PATCH] gh-155433: Fix TaskGroup losing outside cancellation after cancel() --- Lib/asyncio/taskgroups.py | 3 +++ Lib/test/test_asyncio/test_taskgroups.py | 20 +++++++++++++++++++ ...-08-09-16-14-38.gh-issue-155433.KL7tHV.rst | 2 ++ 3 files changed, 25 insertions(+) create mode 100644 Misc/NEWS.d/next/Library/2026-08-09-16-14-38.gh-issue-155433.KL7tHV.rst diff --git a/Lib/asyncio/taskgroups.py b/Lib/asyncio/taskgroups.py index a431b45a19489d..0c1d09ded2f956 100644 --- a/Lib/asyncio/taskgroups.py +++ b/Lib/asyncio/taskgroups.py @@ -151,6 +151,9 @@ async def _aexit(self, et, exc): # If there are no pending cancellations left, # don't propagate CancelledError. propagate_cancellation_error = None + else: + # gh-155433: the remaining cancellation is not ours, don't drop it + propagate_cancellation_error = exceptions.CancelledError() # Propagate CancelledError if there is one, except if there # are other errors -- those have priority. diff --git a/Lib/test/test_asyncio/test_taskgroups.py b/Lib/test/test_asyncio/test_taskgroups.py index bc246400b83e9b..88bb9510af367b 100644 --- a/Lib/test/test_asyncio/test_taskgroups.py +++ b/Lib/test/test_asyncio/test_taskgroups.py @@ -1154,6 +1154,26 @@ async def test_taskgroup_cancel_before_create_task(self): with self.assertRaises(RuntimeError): tg.create_task(asyncio.sleep(1)) + async def test_taskgroup_cancel_keeps_outer_cancellation(self): + # gh-155433: any cancellation from outside the group must propagate. + async def child(): + try: + await asyncio.sleep(10) + finally: + await asyncio.sleep(0.1) + + async def body(): + async with asyncio.TaskGroup() as tg: + tg.create_task(child()) + await asyncio.sleep(0) + tg.cancel() + + task = asyncio.create_task(body()) + await asyncio.sleep(0.01) + task.cancel() + with self.assertRaises(asyncio.CancelledError): + await task + async def test_taskgroup_cancel_before_exception(self): async def raise_exc(parent_tg: asyncio.TaskGroup): parent_tg.cancel() diff --git a/Misc/NEWS.d/next/Library/2026-08-09-16-14-38.gh-issue-155433.KL7tHV.rst b/Misc/NEWS.d/next/Library/2026-08-09-16-14-38.gh-issue-155433.KL7tHV.rst new file mode 100644 index 00000000000000..dc8961e976abbc --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-08-09-16-14-38.gh-issue-155433.KL7tHV.rst @@ -0,0 +1,2 @@ +Fix :class:`asyncio.TaskGroup` losing outside cancellation after +``cancel()``.