Skip to content

extmod/uasyncio: wait_for cancellation bugs #5797

@kevinkk525

Description

@kevinkk525

CancelledError forwarding if wait_for got cancelled (not the task it awaits):

Your assumption "# Ignore CancelledError from aw, it's probably due to timeout" in funcy.py line 20

# Ignore CancelledError from aw, it's probably due to timeout
is incorrect.
As you can see in the testcase "wait_for.test_cancellation_forwarded", if you cancel the caller task of "wait_for", the coro awaited by "wait_for" gets correctly cancelled, but the caller of "wait_for" never gets the Exception raised. The CancelledError gets swallowed by "wait_for" instead of forwarding it.

Wait_for also behaves incorrectly if CancelldError Exceptions are caught inside the task it awaits because they don't get raised to wait_for anymore. However Cpython does also raise those to wait_for even if they are caught in the task wait_for awaits.

All my wait_for testcases (working on upy and cpy) are here: https://gist.github.com/kevinkk525/3313a8d2763031a705e37d1748d1d996

The one in question for all bugs mentioned:

async def test_cancellation_forwarded(catch=False, catch_inside=False):
    res = [False, False]

    async def wait():
        nonlocal res
        try:
            await asyncio.wait_for(awaiting(2, catch_inside), 0.5)
        except asyncio.TimeoutError:
            dprint("Got timeout error")
            res[0] = asyncio.TimeoutError
            raise
        except asyncio.CancelledError:
            dprint("Got canceled")
            if catch:
                res[0] = True
            else:
                raise

    async def killer(t):
        dprint("killer started")
        await asyncio.sleep(0.2)
        dprint("killing wait()")
        t.cancel()

    t = asyncio.create_task(wait())
    k = asyncio.create_task(killer(t))
    try:
        await t
    except asyncio.CancelledError:
        dprint("waiting got cancelled")
        res[1] = asyncio.CancelledError
    return res

Metadata

Metadata

Assignees

No one assigned

    Labels

    extmodRelates to extmod/ directory in source

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions