You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Pool never closes if acquire with timeout is cancelled #547
If you built asyncpg locally, which version of Cython did you use?: N/A
Can the issue be reproduced under both asyncio and uvloop?: Yes
Here's a demo:
importasyncioimportasyncpgasyncdefmain():
# Create a poolpool=awaitasyncpg.create_pool(...)
# An example function using the poolasyncdefuse_pool(pool):
asyncwithpool.acquire(timeout=200):
pass# Schedule the task and canceltask=asyncio.ensure_future(use_pool(pool))
awaitasyncio.sleep(0.0000000001) # Yield to let task starttask.cancel()
print('Closing pool')
awaitpool.close()
print('Closed')
loop=asyncio.get_event_loop()
loop.run_until_complete(main())
loop.close()
This code creates a pool, then starts a task that tries to acquire a connection with a timeout. This task is allowed to start, but is then cancelled. Following this, the pool is closed. The expected behaviour is that the pool should close cleanly, as no connections are in use.
When running this code, I see 'Closing pool' printed, then the script hangs indefinitely. It appears the pool is waiting for the release of the connection, which has not correctly handled the cancellation. When observing this in actual code, printing the pending tasks shows one stuck at PoolConnectionHolder.wait_until_released() (line 229). This suggests that the _in_use future is not being resolved correctly during cancellation.
However, if I remove the timeout=200 on the acquire, the bug goes away. Additionally, the 0.0000000001 second sleep is somewhat important:
Setting this to a higher value eventually leads to the code working, as the task will complete before being cancelled
Removing this sleep also makes the code 'work', as the task is never scheduled.
Effectively, there is a very short 'critical' window (~10us seconds on this machine) during which a cancellation arriving will lead to the pool being unclosable. Hence this bug has been a total pain to hunt for.
changed the title [-]Pool never closes if aquire with timeout is cancelled[/-][+]Pool never closes if acquire with timeout is cancelled[/+]on Mar 27, 2020
Activity
[-]Pool never closes if aquire with timeout is cancelled[/-][+]Pool never closes if acquire with timeout is cancelled[/+]Ensure pool connection is released in acquire when cancelled
Add a workaround for bpo-37658
Add a workaround for bpo-37658
Add a workaround for bpo-37658
Add a workaround for bpo-37658