-
-
Notifications
You must be signed in to change notification settings - Fork 30.9k
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
GH-95289: Always call uncancel() when required #95513
Conversation
Hi, import asyncio
class MyException(Exception):
pass
async def async_fn2():
try:
await asyncio.sleep(0.0)
raise MyException
finally:
print("raise done")
async def main():
task = asyncio.current_task()
try:
async with asyncio.TaskGroup() as tg:
tg.create_task(async_fn2())
await asyncio.sleep(1)
except* (MyException, asyncio.CancelledError) as e:
# How to check a private `_parent_cancel_requested` attr here, outside the class ?
print(f"{e.exceptions} -> {task.cancelling()=}, {tg._parent_cancel_requested=}")
async def supermain():
t = asyncio.create_task(main())
await asyncio.sleep(0)
t.cancel()
print("cancel main task")
await asyncio.sleep(1)
print(f"{t.cancelling()=} must be 1, confirm ?")
asyncio.run(supermain()) |
That code looks racy with the sleep(0.0) calls, but it is correct that since your supermain code cancels main, uncancel will not be called. Note that |
I wonder whether it is important to check if parent task is not |
What problem would that solve? |
dde8683
to
839f7f3
Compare
839f7f3
to
6cd25fc
Compare
Problem is already solved with the 'externally cancel' case. |
Superseded by #95602 which includes tests. |
In
__aexit__()
we should always callself._parent_task.uncancel()
when we calledself._parent_task.cancel()
-- even if the exception being received by__aexit__()
is notCancelledError
(since it may have been suppressed or replaced by another exception).The logic is a bit contorted since we must propagate a cancellation error in two separate situations: