GH-95289: Always call uncancel() when required#95513
GH-95289: Always call uncancel() when required#95513gvanrossum wants to merge 1 commit intopython:mainfrom
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: