Skip to content

Commit 60ba16b

Browse files
committed
fix(client-h2): stop double-decrementing kOpenStreams on stream timeout
The HTTP/2 stream 'timeout' handler in lib/dispatcher/client-h2.js does: stream.on('timeout', () => { const err = new InformationalError(...) stream.removeAllListeners('data') session[kOpenStreams] -= 1 if (session[kOpenStreams] === 0) session.unref() abort(err) }) `abort(err)` ultimately destroys the http2 stream, which fires 'close', and the 'close' listener a few lines above already decrements kOpenStreams: stream.once('close', () => { stream.removeAllListeners('data') session[kOpenStreams] -= 1 if (session[kOpenStreams] === 0) session.unref() }) Result: a single timed-out request knocks the counter down twice and it ends at -1 instead of 0. Future stream accounting on the session is then permanently skewed (the === 0 unref check can never match, and reused-session flows that rely on the counter reaching 0 to release the socket start holding sessions open longer than they should). Leave the decrement to the 'close' handler. The 'timeout' handler only needs to stop the data listener and call abort(); destruction via abort() guarantees 'close' fires exactly once. After this change the repro in the issue reports `open streams after timeout: 0` as expected. Fixes #5073 Signed-off-by: SAY-5 <SAY-5@users.noreply.github.com>
1 parent c7a2901 commit 60ba16b

File tree

1 file changed

+0
-6
lines changed

1 file changed

+0
-6
lines changed

lib/dispatcher/client-h2.js

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -757,12 +757,6 @@ function writeH2 (client, request) {
757757
stream.on('timeout', () => {
758758
const err = new InformationalError(`HTTP/2: "stream timeout after ${requestTimeout}"`)
759759
stream.removeAllListeners('data')
760-
session[kOpenStreams] -= 1
761-
762-
if (session[kOpenStreams] === 0) {
763-
session.unref()
764-
}
765-
766760
abort(err)
767761
})
768762

0 commit comments

Comments
 (0)