-
Notifications
You must be signed in to change notification settings - Fork 57
Description
Describe the bug
There is a race condition in code that handles connection timeout. If you call cancel on a task that is currently pending in create_connection and connection timeout was already fired then asyncio.CancelledError is not propagated and you get asyncio.TimeoutError instead. The main problem is in how timeouts are handled in async_timeout package. When exitting the context manager after timeout had passed all CancelledError exceptions are swallowed and TimeoutError is raised instead. Unfortunately this is true also if you explicitly cancel the task yourself.
The main problem is that you cannot cancel a task that is using aiohttp because you never know if CancelledError will be raised.
To Reproduce
EDIT: THIS REPRODUCER DOES NOT SHOW THE BEHAVIOUR CORRECTLY - PLEASE REFER TO COMMENTS BELLOW!
import asyncio
from async_timeout import timeout
async def test_task():
with timeout(1):
await asyncio.sleep(10)
async def main():
t = asyncio.create_task(test_task())
await asyncio.sleep(2)
t.cancel()
try:
await t
except asyncio.TimeoutError:
print("Raised TimeoutError")
except asyncio.CancelledError:
print("Raised CancelledError")
asyncio.run(main())Expected behavior
asyncio.CancelledError should never be suppressed when you cancel the task explicitly.
Logs/tracebacks
---Python Version
Python 3.8.10aiohttp Version
3.7.4.post0multidict Version
4.7.6yarl Version
1.6.0OS
Linux
Related component
Client
Additional context
No response
Code of Conduct
- I agree to follow the aio-libs Code of Conduct