Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Different cancel scope behaviour on asyncio vs Trio #698

Open
2 tasks done
arthur-tacca opened this issue Mar 13, 2024 · 2 comments
Open
2 tasks done

Different cancel scope behaviour on asyncio vs Trio #698

arthur-tacca opened this issue Mar 13, 2024 · 2 comments
Labels
bug Something isn't working

Comments

@arthur-tacca
Copy link

Things to check first

  • I have searched the existing issues and didn't find my bug already reported there

  • I have checked that my bug is still present in the latest release

AnyIO version

4.3.0

Python version

3.10.13; 3.12.1

What happened?

Run a cancel scope within another cancel scope. Cancel the inner one then await something so that a cancellation exception is raised, but during handling also cancel the outer one (but do not call any more unshielded async functions before the end of the inner block). With the asyncio backend, the inner block will swallow the cancellation exception, allowing the outer block to continue running (until the next unshielded await in it), while the Trio backend will propagate the exception right out to the end of the outer block

By the way, the Trio docs give the impression that it is meant to work the same way as the asyncio backend does. (See discussion on Trio Discourse: Do Cancelled exceptions “know” which block they belong to?)

How can we reproduce the bug?

import anyio

async def cancel_check():
    with anyio.CancelScope() as outer_scope:
        with anyio.CancelScope() as inner_scope:
            await anyio.sleep(0.1)
            inner_scope.cancel()
            print("inner cancelled")
            try:
                await anyio.sleep(0.1)
            finally:
                outer_scope.cancel()
                print("outer cancelled")
            print("should not be here inner")
        print("should not be here outer")
    print("all done")

anyio.run(cancel_check, backend="trio")

Output with Trio backend:

inner cancelled
outer cancelled
all done

Output with asyncio backend:

inner cancelled
outer cancelled
should not be here outer
all done
@arthur-tacca arthur-tacca added the bug Something isn't working label Mar 13, 2024
@arthur-tacca
Copy link
Author

As my second comment at the linked post says, Trio changed to the current behaviour in version 0.11.0 (2019-02-09).

@agronholm
Copy link
Owner

I tried fixing this by raising a new CancelledError from CancelScope.__exit__(), but that interacted poorly with task groups, as they're not prepared to handle exceptions falling out of that method (timeouts in taskgroup.cancel_scope are not a thing).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants