Repository navigation
Don't touch a QUIC connection's state after it is gone - #182
Merged
jagerman merged 3 commits intoOct 7, 2026
Merged
Conversation
On a normal close, libquic fails a stream's pending requests from close_all_streams() while the connection still exists; it only fails them from ~sent_request when a stream outlives its connection.
Member
|
Minor comment clarification pushed; otherwise LGTM. |
Member
|
Also worth noting: both issues fixed here were possible before 1.11; I think 1.11 just made them a little more likely. |
Member
|
(Merged with CI failing: the failures are all from a temporary fmt 1.11 transition causing issues with spdlog in debian-sid that should go away in a couple of days). |
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.
Two fixes to
QuicTransport's per-connection bookkeeping, both about state outliving a connection. They're separate commits so the second can be dropped on its own.1. Don't dereference a connection that is already gone when a response arrives
The response handler in
_send_on_connectionlooks up the request's connection to return the stream to the pool, or close it:When the connection has already closed,
connis null, so the first test fails and theelse ifdereferences null. The code predates the libquic bump, but libquic 1.11 now always fires a request's callback, including from~sent_requestas the connection is torn down (oxen-libquic005631f/13d4f40). That makes "response arrives, connection gone" an ordinary teardown path, e.g. on suspend, on a node dropping us, or on network loss. With the connection gone there is nothing to return to the pool or close, and any ids pooled for it are dead, so those are dropped too.2. Clear only the closed connection's state when a connection fails
The connection-closed callback ignored the connection it was given, and
_fail_connectioncleaned up by pubkey: it extracted_active_connection_ids[pubkey], then erased the stream ids of whichever connection that pubkey currently mapped to. A newer connection to the same node can be established before an old one's close arrives. The send path already handles "connection no longer exists" by dropping the mapping and failing the request, which the caller then retries. When the old close lands after that:The closed callback now passes
conn.reference_id(), and_fail_connectionerases that connection's stream ids. It removes the pubkey's mapping only if the mapping still points at that connection. Callers without a connection (theconnectexception paths) keep the old behaviour.Not changed, and worth a look separately: the rest of
_fail_connection(failing pending verification callbacks, failure listeners, node-failure reporting on handshake timeout) still acts per pubkey. So a stale close for an old connection can still fail callbacks that belong to a newer attempt on the same node.Tested: both commits compile in Session iOS's
Debug_Compile_LibSessionbuild (Xcode 27; networking enabled) on top ofdev+ #181, and clang-format-19 is clean. The quic transport unit tests were not run; this was not built with tests on locally.