Uh oh!
There was an error while loading. Please reload this page.
Race Condition with Asyncio Cancelled Tasks #783
Replies: 2 comments 7 replies
It's strange because at the end of the program, the connection pool is full of closed connections; these connections were supposed to be removed from the pool, but that doesn't happen. |
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
@tomchristie thanks for taking the time to look into this. I'll admit this isn't the first cancellation-related race condition we've run into with asyncio, so I'm not opposed to a trio migration, although I just finished converting our synchronous codebase to asyncio, so that particular idea causes me some amount of weariness. 🫠 (if you felt the same way about this very issue, I wouldn't blame you). The examples you provided indeed do not reveal the bug. But I was able to reproduce it in trio by iterating again with the same httpcore client, like so: importtrioimporthttpcoreTIMEOUT= {"read": 5, "write": 5, "connect": 5, "pool": 5}
asyncdefsend_request(client, seen_response):
response=awaitclient.request("GET", "http://127.0.0.1:8000", extensions={"timeout": TIMEOUT})
# Print the first response that we see and set the "seen_response" flag.ifnotseen_response.is_set():
print(response)
seen_response.set()
asyncdefmain():
asyncwithhttpcore.AsyncConnectionPool() asclient:
while1: # <-----------------asyncwithtrio.open_nursery() asnursery:
# This event is used to signal the first response we recieve.seen_response=trio.Event()
# Kick off one hundred HTTP requests.foridxinrange(100):
nursery.start_soon(send_request, client, seen_response)
# As soon as we see a response we can cancel out of the nursery,# rather than allowing all tasks to complete.awaitseen_response.wait()
nursery.cancel_scope.cancel()
trio.run(main)For me, this reproduces the Let me know what you think. |
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Hello, I was directed to open a discussion here based on this one over at httpx.
The gist of the race condition is that when a web request is cancelled within a specific time window, it will degrade the state of the connection pool, leaving it unable to issue further requests.
It can be reproduced with the following code:
In essence, this code will create a batch of web requests, get the first successful result, then cancel the rest, rinse and repeat.
On my machine it runs for about ten to twenty iterations, hangs for the specified timeout (5 seconds), then throws an httpx.PoolTimeout error and fails to recover.
Thanks!
All reactions