Skip to content

asyncio.TaskGroup hangs on cancel with eager task factory #155418

Description

@deadlovelll

Bug report

Bug description:

With eager TF, a child task that calls tg.cancel() before it suspends is never cancelled, and the group hangs forever. This happens if we dont have a suspension point before cancelling the group in the child, abort() happens before the task added to the self._tasks and run on empty list. Then __aexit__ hangs on await self._on_completed_fut that tries to wait task that is not cancelled

Repro:

import asyncio


async def child(tg, done):
    tg.cancel()
    await done.wait()


async def main():
    done = asyncio.Event()
    async with asyncio.TaskGroup() as tg:
        tg.create_task(child(tg, done))
    print("group exited")


loop = asyncio.new_event_loop()
loop.set_task_factory(asyncio.eager_task_factory)
loop.run_until_complete(main())

Expected output will be

group exited

But actually there will be no print

Proposed fix - add the check before returning the task

        self._tasks.add(task)
        task.add_done_callback(self._on_task_done)
        if self._aborting and not task.done():
            task.cancel()
        try:
            return task
        finally:
            # gh-128552: prevent a refcycle of
            # task.exception().__traceback__->TaskGroup.create_task->task
            del task

I have a fix ready

CPython versions tested on:

CPython main branch

Operating systems tested on:

macOS

Linked PRs

Metadata

Metadata

Assignees

No one assigned

    Labels

    stdlibStandard Library Python modules in the Lib/ directorytopic-asynciotype-bugAn unexpected behavior, bug, or error

    Projects

    Status
    Todo

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions