-
Notifications
You must be signed in to change notification settings - Fork 117
Deadlock in AsyncConnectionPool #454
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Hello there! Disclaimer: @f0ff886f and I work together. TL;DR: It seems that the issue is in This code snippet reproduces the deadlock. import asyncio
import anyio
class Holder:
def __init__(self):
# self.lock = asyncio.Lock()
self.lock = anyio.Lock()
async def work(self, index):
print(f"Trying to acquire {index}")
async with self.lock:
print(f"Doing index {index}")
await asyncio.sleep(5)
async def main_anyio():
holder = Holder()
t1 = asyncio.create_task(holder.work(1), name="holder 1")
t2 = asyncio.create_task(holder.work(2), name="holder 2")
print("Tasks created")
await asyncio.sleep(0)
print("Cancelling t1")
t1.cancel()
print("Waiting for t2")
await asyncio.gather(t2)
if __name__ == "__main__":
asyncio.run(main_anyio()) The explanation is that the first task trying to acquire the So the lock remains acquired and every other task waiting for an unlock. This does not happen if the lock is an I will fill a bug in the |
Okay, good work on this one folks, thanks. We might be able to switch to using either |
There is a fix: agronholm/anyio#399 |
Hi @agronholm thank you for the super fast turnaround! I'll poke @graffic to take a look at the PR as he seems to understand the deadlock well. |
I'll close this off, since I assume it is resolved as of |
Hello, first of all I would like to apologize for not providing a repro for this bug as it is something I have hit only once but it is a very nasty hang.
I have a tool that uses
httpx
and issues HTTP POSTs concurrently with something like this:Where
c.stop()
is:And lastly,
self._client
is simply:self._client = httpx.AsyncClient(base_url=url, timeout=15)
Recently, this stop sequence just stalled forever, and the clients never received a stop POST.
Digging into the running process with
pyrasite-ng
and the following toy code:(the actual command was:
pyrasite --output localterm 32953 debug.py
)I could see something like this for the stop coroutines:
There looks to be a deadlock somewhere in the connection pool and its use of httpcore's
AsyncLock
-> anyio'sLock
... unfortunately I cannot repro this easily and I don't know if there is any other detail I could provide to help.I will leave the hung context open till the weekend, but if I could share any more info please let me know.
The text was updated successfully, but these errors were encountered: