Do not give up the queue because one accept failed - #790
Merged
Conversation
Listen returned on any SocketException from Accept, without looking at the error code or at cancellation. That treats a failure of one accept as a failure of the listener, and the two are not the same thing at all. A peer that resets while its connection is still sitting in the backlog surfaces exactly this way - WSAECONNRESET on Windows, ECONNABORTED on BSD and macOS - and is common enough that Kestrel retries it by name. The consequence here is worse than a dropped connection: the socket stays bound, so nobody else can take the queue for the life of the process, and every later client lands in a backlog that nothing is draining. PiperServer already continues in the same situation. Return only when cancelled, or on OperationAborted and Interrupted, which are how a stopped listener reports itself when the token has not been observed yet. The tests pin the rule rather than the race. I wrote an end to end one first - twenty abortive closes, then a real exchange - and deleted it after confirming it passes with the old `return` still in place: on Windows the accept succeeds and the reset surfaces later, during the read, which a different catch already handles. A test that cannot fail is worse than no test.
…peer-reset # Conflicts: # src/DiffEngine.Tests/ViewerProtocolTests.cs
This was referenced Aug 26, 2026
This was referenced Aug 27, 2026
Closed
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.
Listen returned on any SocketException from Accept, without looking at the error
code or at cancellation. That treats a failure of one accept as a failure of the
listener, and the two are not the same thing at all.
A peer that resets while its connection is still sitting in the backlog surfaces
exactly this way - WSAECONNRESET on Windows, ECONNABORTED on BSD and macOS - and
is common enough that Kestrel retries it by name. The consequence here is worse
than a dropped connection: the socket stays bound, so nobody else can take the
queue for the life of the process, and every later client lands in a backlog
that nothing is draining. PiperServer already continues in the same situation.
Return only when cancelled, or on OperationAborted and Interrupted, which are
how a stopped listener reports itself when the token has not been observed yet.
The tests pin the rule rather than the race. I wrote an end to end one first -
twenty abortive closes, then a real exchange - and deleted it after confirming
it passes with the old
returnstill in place: on Windows the accept succeedsand the reset surfaces later, during the read, which a different catch already
handles. A test that cannot fail is worse than no test.