Skip to content

Cancellation blocks task_status.started #2544

Open
@smurfix

Description

@smurfix

The problem: when a task starts a shielded subtask, but is cancelled before the subtask re-parents itself, the cancellation isn't propagated until the subtask ends.

Consider this code:

import trio

async def t(task_status):
    with trio.CancelScope(shield=True) as sc:  # turn off shielding, the code works
        await trio.sleep(2)
        print("Send",sc)
        task_status.started(sc)
        await trio.sleep(3)
        print("Terminating")

async def r(tg):
    sc = await tg.start(t)
    print("Receive",sc)
    sc.cancel()

async def main():
    async with trio.open_nursery() as tg:
        tg.start_soon(r,tg)
        await trio.sleep(1)
        tg.cancel_scope.cancel()  # comment this off, the code works

trio.run(main)

What I expect to happen is that tg.start returns the value from task_status.started, task t gets cancelled, this code takes one second to run.

In my "real" usecase the subtask starts a database connection which must be (a) cached and (b) closed properly. Thus turning off the shield won't work. The cancellation in the last line of main is a stand-in for any kund of exception that might happen in the rest of the program.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions