Skip to content

Async: cancelling the task that holds the processing lock leaves queued send() callers pending #690

Closed

Description

@fgmacedo

On the async engine, when the coroutine that is running the processing loop is cancelled (for example by asyncio.wait_for or a request timeout around await sm.send(...)), other coroutines awaiting send() of events queued behind it never return. CancelledError is a BaseException, so the exception path added in #688 does not run.

class N(StateMachine):
    a = State(initial=True); b = State()
    go = a.to(b); step = a.to.itself() | b.to.itself()
    async def on_go(self): await asyncio.sleep(10)
    def on_step(self): return "stepped"

holder = asyncio.create_task(sm.send("go"))
await asyncio.sleep(0.05)
other = asyncio.create_task(sm.send("step"))
await asyncio.sleep(0.05)
holder.cancel()
await asyncio.wait_for(other, 2)  # TimeoutError: never answered

A later send() works, so the machine recovers, but the queued callers stay pending forever. Reported as pre-existing on v3.2.1 in #688. Expected: queued callers are answered (their events processed, or rejected) instead of hanging.

Activity

  1. added this to the 3.2.2 milestone on Oct 13, 2026
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

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions