aiohttp swallows asyncio.CancelledError during connection timeout · Issue #229 · aio-libs/async-timeout (original) (raw)

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

aiohttp Version

multidict Version

yarl Version

OS

Linux

Client

Additional context

No response

Code of Conduct