anyio icon indicating copy to clipboard operation
anyio copied to clipboard

`CancelScope.cancel` does not trigger cancellation if called before we enter the cancel scope

Open frederikaalund opened this issue 2 years ago • 2 comments

The following code example shows the issue:

import anyio

async def main():
    cancel_scope = anyio.CancelScope()
    cancel_scope.cancel()  # We call `cancel` before `__enter__`
    with cancel_scope:
        await anyio.sleep(1)  # Checkpoint to allow anyio to check for cancellation
        cancel_scope.cancel()  # Try `cancel` again just for good measure
        await anyio.sleep(1)  # Checkpoint to allow anyio to check for cancellation
        print("foo")  # We get this far even though we cancelled the cancel scope long before.

anyio.run(main)

This code prints foo. I expect it to print nothing because we cancelled the cancel scope long before the call to print.

If I remove the call to CancelScope.cancel before the call to CancelScope.__enter__ then the code works as expected (prints nothing).

frederikaalund avatar Apr 11 '22 13:04 frederikaalund

Never have I imagined a situation where somebody tries to do something with a cancel scope before entering it.

agronholm avatar May 13 '22 09:05 agronholm

It is an edge case, indeed. :) Alternatively, let

cancel_scope.cancel()  # We call `cancel` before `__enter__`

raise a RuntimeError("Cancel called before __enter__"). This way, the user knows up front that this is not supported.

frederikaalund avatar May 13 '22 11:05 frederikaalund

I decided to implement this on asyncio because it also works on Trio this way.

agronholm avatar Oct 02 '22 14:10 agronholm