Skip to content

Bound close(timeout) around a pending cancel - #1361

Open
gyanu2507 wants to merge 1 commit into
MagicStack:masterfrom
gyanu2507:fix/close-timeout-pending-cancel
Open

gyanu2507 wants to merge 1 commit into
MagicStack:masterfrom
gyanu2507:fix/close-timeout-pending-cancel

Conversation

@gyanu2507

@gyanu2507 gyanu2507 commented Sep 18, 2026

Copy link
Copy Markdown

Fixes #1356.

close(timeout=) waits for cancel_waiter before it applies timeout. That future is only completed when ReadyForQuery arrives on the original socket. _on_connection_lost resolves waiter and leaves the cancel futures pending, so a frozen server (or a pooler that then drops the client) can leave close() hung forever.

SQLAlchemy's asyncpg dialect hits this when it invalidates a connection after TimeoutError with close(timeout=2).

The cancel wait now uses the same timeout, a lost transport completes the cancel futures, and abort() still drops the socket if close() already set closing.

close() awaited cancel_waiter with no timeout, and connection_lost
only resolved waiter. A frozen server left close() hanging even
after the socket dropped.

Fixes MagicStack#1356
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Connection.close(timeout=) waits forever on a pending cancel when the server never acknowledges it

1 participant