Skip to content

fix(h2): release completed requests from queue#5569

Merged
mcollina merged 4 commits into
nodejs:mainfrom
staylor:fix/h2-abort-queue-retention
Jul 20, 2026
Merged

fix(h2): release completed requests from queue#5569
mcollina merged 4 commits into
nodejs:mainfrom
staylor:fix/h2-abort-queue-retention

Conversation

@staylor

@staylor staylor commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

This relates to...

Fixes #5566.

Rationale

The HTTP/2 in-order completion optimization introduced in #5483 advanced kRunningIdx without clearing the completed request's queue slot. Until the periodic queue compaction ran, each dead prefix slot retained its Request, whose controller retained the ClientHttp2Stream and the rest of the fetch graph. Under sustained HTTP/2 abort churn this retained native response buffers and caused memory growth. A 20,000-request reproduction at 50% aborts grew the heap by 10.6 MB before this change and 2.8 MB after it, matching the pre-#5483 baseline.

A stream can also close after its request has already been marked aborted. Terminal stream cleanup must still finalize that request even though onResponseEnd must not run.

Changes

Features

N/A

Bug Fixes

  • Clear an in-order completed HTTP/2 request's queue slot before advancing kRunningIdx, preserving the O(1) fast path and matching the existing HTTP/1 queue behavior.
  • Finalize terminal HTTP/2 streams independently of whether the response ended successfully.
  • Add regression coverage for an already-aborted request closing without response completion.

Breaking Changes and Deprecations

N/A

Status

The HTTP/2 in-order completion fast path advanced the running index but retained the completed Request in its queue slot until batched compaction. Under sustained abort churn, each retained Request pinned its stream and fetch graph, including native response buffers.

Clear the completed slot before advancing, preserving the O(1) fast path, and finalize closed streams even when the Request was already marked aborted.

Fixes: nodejs#5566
Signed-off-by: Scott Taylor <scott.c.taylor@mac.com>
Assisted-By: devx/4ad398e1-8641-4e85-a62d-cb78992a7aae
@codecov-commenter

codecov-commenter commented Jul 17, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 93.47%. Comparing base (87270e4) to head (7ffd5c3).
⚠️ Report is 3 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #5569   +/-   ##
=======================================
  Coverage   93.47%   93.47%           
=======================================
  Files         110      110           
  Lines       37507    37561   +54     
=======================================
+ Hits        35059    35111   +52     
- Misses       2448     2450    +2     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@mcollina
mcollina requested a review from trivikr July 17, 2026 15:02

@mcollina mcollina left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

lgtm

@mcollina
mcollina requested a review from metcoder95 July 17, 2026 15:38
@mcollina

Copy link
Copy Markdown
Member

I'm relatively concerned by this PR (and previous ones) that do not actually provide e2e tests.

Signed-off-by: Scott Taylor <scott.c.taylor@mac.com>
Assisted-By: devx/7d65db46-a09e-471a-9e1c-abdaa5accba8
@staylor

staylor commented Jul 19, 2026

Copy link
Copy Markdown
Contributor Author

Thanks @mcollina — agreed. I’ve added an end-to-end regression test in 84ab33d. It uses a real TLS HTTP/2 server through the public fetch/Client APIs, aborts an in-flight response while keeping the session open and usable, and verifies that the aborted fetch graph is released. The test fails against the parent commit and passes with this fix.

@metcoder95 metcoder95 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

small comment; rest lgtm

Comment thread test/fetch/issue-5566.js Outdated

@mcollina mcollina left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

lgtm

mcollina and others added 2 commits July 20, 2026 04:07
Co-authored-by: Carlos Fuentes <me@metcoder.dev>
Signed-off-by: Matteo Collina <hello@matteocollina.com>

@mcollina mcollina left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

lgtm

@mcollina
mcollina merged commit f87273e into nodejs:main Jul 20, 2026
38 checks passed
@github-actions github-actions Bot mentioned this pull request Jul 20, 2026
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.

Memory leak: aborted HTTP/2 requests strand the response body and leak the request graph (regression in #5483 / 8.6.0)

4 participants