Skip to content

fix: run idle socket validation off setImmediate instead of setTimeout#5499

Open
carlotestor wants to merge 1 commit into
nodejs:mainfrom
carlotestor:fix/idle-validation-setimmediate
Open

fix: run idle socket validation off setImmediate instead of setTimeout#5499
carlotestor wants to merge 1 commit into
nodejs:mainfrom
carlotestor:fix/idle-validation-setimmediate

Conversation

@carlotestor

@carlotestor carlotestor commented Jul 3, 2026

Copy link
Copy Markdown

Summary

Fixes #5493

Schedule the idle-socket validation deferral with setImmediate instead of setTimeout(..., 0) in scheduleIdleSocketValidation (lib/dispatcher/client-h1.js), and cancel it with clearImmediate accordingly (clearTimeout does not cancel an Immediate, so the pending callback would otherwise fire after socket cleanup — harmlessly, since it self-guards, but the handle should be cancelled properly). The now-meaningless 0 delay argument is dropped.

The validation only needs the event loop to surface any unsolicited bytes / FIN / RST already pending on the reused idle socket before the next request is written. The setImmediate check phase still runs after the poll phase, so those events are processed first — but without the ~1ms+ timer floor that setTimeout(0) pays on every idle-socket reuse.

Measured

Loopback HTTP, keep-alive Agent (pipelining: 1), 2000 sequential requests + 8-wide bursts, node v22.22.1 (full harness in #5493):

sequential p50 8-wide burst p50
main (setTimeout(0)) ~1.4 ms ~1.9 ms
this patch (setImmediate) 0.076 ms 0.446 ms
7.27.2 (pre-validation baseline) 0.078 ms 0.49 ms

i.e. the GHSA-35p6-xmwp-9g52 mitigation is retained at effectively zero latency cost.

Tests

  • node --test test/response-queue-poisoning.js test/issue-810.js test/client-keep-alive.js — 15/15 pass with the patch (including the poisoned-idle-socket regression test)

Notes

  • The kIdleSocketValidationTimeout symbol now holds an Immediate; left the name unchanged to keep the diff minimal, happy to rename if preferred.
  • Immediate.unref() exists, so the existing .unref?.() call keeps working.

Disclosure

This pull request (analysis, patch, benchmarks, and text) was created by Claude (model: claude-fable), an AI assistant by Anthropic, operating under human direction. Please review accordingly.

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.

Idle-socket validation adds ~1.3ms to every keep-alive request reuse (setTimeout(0) in scheduleIdleSocketValidation)

2 participants