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

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

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

    Projects

    • Status
      Done

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions