Repository navigation
Let cancel_query! cancel a statement after an interrupt closed the socket - #45
Merged
Merged
Conversation
The fake server never answers the statement, so the interrupt lands in the read loop and the driver closes the socket. The cancel must still reach the server with the pid and key the connection holds. The Docker case checks that the interrupted statement stops on a real server. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
cancel_query! refused a connection whose socket was closed, so a statement interrupted mid-query kept running on the server with no way to stop it from the driver. The CancelRequest goes over its own connection and needs only the backend pid and cancel key, which the connection keeps after the socket closes, as a libpq PGcancel does. Drop the socket check and the trylock that only guarded it. Fixes #44 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The statement an interrupt left running stops when it finishes or is cancelled. With `reconnect=true`, using the connection again opens a new session and replaces the stored pid and cancel key, so a cancel must come first to reach the abandoned statement. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Merged
quinnj
referenced
this pull request
Nov 5, 2026
Co-authored-by: Jacob Quinn <quinn.jacobd@gmail.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This was referenced Nov 5, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
An
InterruptExceptionthat lands while a statement runs closes the socket, because the stream position is unknown, but the statement keeps running on the server.cancel_query!then refused the connection with "cannot cancel query: connection not open", so the driver had no way to stop that statement (#44). The CancelRequest goes over its own connection and needs only the backend pid and cancel key, which the connection keeps, the same way a libpqPGcanceloutlives itsPGconn.What changed
cancel_query!no longer checks the socket, and drops thetrylockblock that existed only for that check. It sends the request with the pid and key the connection holds.pg_sleepon a real server and checks that the statement stops.Fixes #44
Scope
Only the refusal changes. The interrupt path stays as it is: the socket closes and the connection cannot be reused, which matches MySQL.jl, where a broken session keeps its connection id so the user can run
KILL QUERY. Sending the cancel automatically when an interrupt lands, as psql does, is a separate decision.Blast radius
cancel_query!on a connection closed withclose(conn)now sends a request that the server ignores, because that backend has exited, instead of throwing. No other code read the removed check. With #42 (Terminate on close) the two changes touch different functions and merge cleanly in either order.Verification
cancel after an interrupt closed the socket | 2 pass, 1 error, the error beingcannot cancel query: connection not openthrown fromcancel_query!. After the fix: 43 of 43 in that file, three runs.SELECT pg_sleep(30)left the backend active,cancel_query!on the closed connection sent the request, and the server loggedcanceling statement due to user requestandconnection to client lost.pidandskeyreads match the path a busy connection already took, and a reconnect by another task replaces both fields under its lock, so a stale pair only yields a request the server ignores.cancel_requeststill throws when it cannot deliver the request or would downgrade TLS or GSS.🤖 Generated with Claude Code