Skip to content

fix(ext/node): fix closeIdleConnections destroying active connections#33596

Merged
bartlomieju merged 1 commit into
mainfrom
fix/http-server-close-idle-connections
Apr 27, 2026
Merged

fix(ext/node): fix closeIdleConnections destroying active connections#33596
bartlomieju merged 1 commit into
mainfrom
fix/http-server-close-idle-connections

Conversation

@bartlomieju

Copy link
Copy Markdown
Member

Summary

  • closeIdleConnections() only checked !socket._httpMessage to
    determine if a connection was idle. This incorrectly treated
    connections that had never completed a request (e.g. still receiving
    headers) as idle, destroying them alongside truly idle keep-alive
    connections.
  • Track whether a socket has ever completed a request-response cycle via
    _httpMessageDetached flag set in detachSocket(), and only close
    sockets that have no active response AND have previously served one.
  • Enroll test-https-server-close-idle.js and
    test-http-server-close-idle.js node compat tests.

Test plan

  • ./x test-compat test-https-server-close-idle.js passes (was failing)
  • ./x test-compat test-http-server-close-idle.js passes (newly enrolled)
  • ./x test-compat test-https-server-close-all.js still passes
  • ./x test-compat test-http-server-close-idle-wait-response.js still passes

closeIdleConnections() only checked `!socket._httpMessage` to determine
if a connection was idle. This incorrectly treated connections that had
never completed a request (e.g. still receiving headers) as idle,
destroying them alongside truly idle keep-alive connections.

Track whether a socket has ever completed a request-response cycle via
`_httpMessageDetached` and only close sockets that have no active
response AND have previously served one.

@lunadogbot lunadogbot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM as a targeted fix -- the _httpMessageDetached flag is set unconditionally in detachSocket() (line 317) which runs when a ServerResponse finishes, so it cleanly distinguishes 'fresh connection still receiving first headers' (flag false, the bug case) from 'idle keep-alive after at least one completed response' (flag true). The check !socket._httpMessage && socket._httpMessageDetached only destroys sockets that have served at least one request and have no response in flight. Verified against the 3 enrolled tests by name -- test-http-server-close-idle-wait-response still passing implies the in-flight-response branch (socket._httpMessage non-null) still protects an active write.

One residual race to think about: between a keep-alive cycle's response completing (detachSocket sets flag=true) and the next request reaching the point where assignSocket re-binds _httpMessage, the socket has !_httpMessage && _httpMessageDetached -- both conditions for 'idle' -- but it's actively parsing the next request's headers. A closeIdleConnections() call in that window would destroy an in-progress connection. Node guards this by also checking parser.incoming.complete (see lib/_http_server.js's check), which excludes sockets that are mid-message. Worth either matching that extra condition, or confirming via the test suite that the window is too short to hit in practice (the existing tests pass, so the answer is probably the latter). Not a blocker; flagging so it doesn't surprise you when a future user reports 'closeIdleConnections killed my keep-alive connection during request 2'.

@bartlomieju
bartlomieju merged commit 185752b into main Apr 27, 2026
112 checks passed
@bartlomieju
bartlomieju deleted the fix/http-server-close-idle-connections branch April 27, 2026 18:59
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.

2 participants