Skip to content
Closed
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions Lib/asyncio/taskgroups.py
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,11 @@ def create_task(self, coro, *, name=None, context=None):
else:
self._tasks.add(task)
task.add_done_callback(self._on_task_done)
if self._aborting:
# gh-128550: if this task is eager it might have started
# another eager task that aborts us, if so we must cancel
# this task.
task.cancel()
return task

# Since Python 3.8 Tasks propagate all exceptions correctly,
Expand Down
24 changes: 24 additions & 0 deletions Lib/test/test_asyncio/test_taskgroups.py
Original file line number Diff line number Diff line change
Expand Up @@ -997,6 +997,30 @@ class MyKeyboardInterrupt(KeyboardInterrupt):
self.assertIsNotNone(exc)
self.assertListEqual(gc.get_referrers(exc), no_other_refs())

async def test_cancels_task_if_created_during_creation(self):
ran = False
class MyError(Exception):
pass

try:
async with asyncio.TaskGroup() as tg:
async def third_task():
raise MyError("third task failed")

async def second_task():
nonlocal ran
tg.create_task(third_task())
with self.assertRaises(asyncio.CancelledError):
await asyncio.sleep(0) # eager tasks cancel here
await asyncio.sleep(0) # lazy tasks cancel here
ran = True

tg.create_task(second_task())
except* MyError as excs:
exc = excs.exceptions[0]

self.assertIsInstance(exc, MyError)
self.assertTrue(ran)

if __name__ == "__main__":
unittest.main()
Loading