Uh oh!
There was an error while loading.Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork33.7k
Description
Bug report
Today I came across the following problem:
importasyncioready=asyncio.Event()asyncdeftask_func():try:ready.set()awaitasyncio.sleep(1)exceptasyncio.CancelledError:# this is required, otherwise a TimeoutError is not created below,# instead, the timeout-generated CancelledError is just raised upwards.asyncio.current_task().uncancel()finally:# Perform some cleanup, with a timeouttry:asyncwithasyncio.timeout(0):awaitasyncio.sleep(1)exceptasyncio.TimeoutError:passasyncdefmain():task=asyncio.create_task(task_func())awaitready.wait()awaitasyncio.sleep(0.01)# the task is now sleeping, lets send it an exceptiontask.cancel()# We expect the task to finish cleanly.awaittaskasyncio.run(main())
The documentation mentions that sometimes an application may want to suppressCancelledError. What it fails
to mention is that unless the cancel state is subsequently cancelled withtask.uncancel(), the task remains in a
cancelled state, and context managers such asasyncio.timeout will not work as designed. However,task.uncancel()
is not supposed to be called by user code.
I think the documentation should mention this use case fortask.uncancel(), particularly in the context of catching (and choosing to ignore)CancelledError.
This could also be considered a bug inasyncio.timeout. It prevents the use of the Timeout context manager within cleanup code, even if the intention isnot to ignore aCancelledError.
It should also be noted that the libraryasyncio_timeout on which theasyncio.timeout implementation is based, does not have this problem. Timeouts continue to work as designed, even if the task has been previously cancelled.
Your environment
- CPython versions tested on: 3.11
Linked PRs
Metadata
Metadata
Assignees
Projects
Status