Repository navigation
fix(net): close the connection when onOpen throws - #10
Merged
Merged
Conversation
When onOpen throws, PersistentConnection dropped its reference to the connection without closing it. Such an error does not necessarily mean the connection is already closed: a protocol-level error (e.g. an error frame sent by the server) can be thrown while the underlying socket is still open. Nothing references the connection after that, so it stayed open until the peer closed it, and every reconnect leaked another one. The default onError is affected as well, since it returns 'close' for such errors without closing the connection. Close the old connection before calling onClose/onError, and document that onError receives an already closed connection in this case. Add regression tests for both the 'reconnect' and 'close' actions.
commit: |
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.
Problem
When
onOpenthrows,PersistentConnection#loop()sets#connectiontoundefinedbut never closes the connection. That kind of error doesn't always mean the connection is already closed. A protocol-level error can be thrown while the socket is still open, for example when the server replies with an error but keeps the connection. After that nothing holds a reference to the connection, so it stays open until the peer closes it.If
onErrorreturns'reconnect', every such error leaks one more socket. In a real deployment this built up to ~10k sockets inESTABLISHEDstate in a single process.The default
onErrorhas the same problem. It returns'close'for anything that isn't aConnectionClosedError, the loop exits, and the connection is never closed.Fix
Right after detaching the old connection, close it before calling
onClose/onError. Any error fromclose()is ignored because the connection may already be closed. I also updated theonErrordoc comment to say it receives an already-closed connection in this case.Testing
'reconnect'and'close'actions. Both fail without the fix ("expected close to be called once, but got 0 times").vitest run packages/net: 149 passed.eslintandtscreport no errors.Repro (real TCP sockets)
AI-assisted: I investigated this and wrote the fix with help from Claude Opus 5.5 in Claude Code. I have reviewed the change and verified it myself.