Skip to content

http2: send deferred RST_STREAM on stream destroy - #67372

Open
inoway46 wants to merge 1 commit into
nodejs:mainfrom
inoway46:http2-rst-on-destroy-after-close
Open

inoway46 wants to merge 1 commit into
nodejs:mainfrom
inoway46:http2-rst-on-destroy-after-close

Conversation

@inoway46

@inoway46 inoway46 commented Nov 10, 2026 •

Copy link
Copy Markdown
Contributor

close() with NO_ERROR waits for 'finish' before sending RST_STREAM. If the body is stuck behind flow control and the stream is destroyed first, RST_STREAM is never sent and nghttp2 keeps the stream open. On the next WINDOW_UPDATE, OnRead finds no stream and returns 0 without EOF, so nghttp2 sends empty DATA frames in a loop until the process runs out of memory.

The issue reports this for client requests, but server responses are affected in the same way.

Send the deferred RST_STREAM in _destroy(). As a backstop, return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE from OnRead when the stream is gone, which nghttp2 documents as the way to reset a stream on error. Add regression tests for client and server streams.

Both tests run out of memory on current main, v22.23.4, v24.22.2 and v26.13.0, and pass with this change.

Fixes: #67363

@nodejs-github-bot

Copy link
Copy Markdown
Collaborator

Review requested:

  • @nodejs/http2
  • @nodejs/net

@nodejs-github-bot nodejs-github-bot added c++ Issues and PRs that require attention from people who are familiar with C++. http2 Issues and PRs related to the http2 subsystem. needs-ci PRs that need a full CI run. labels Nov 10, 2026
close() with NO_ERROR waits for 'finish' before sending RST_STREAM.
If the body is stuck behind flow control and the stream is destroyed
first, RST_STREAM is never sent and nghttp2 keeps the stream open.
On the next WINDOW_UPDATE, OnRead finds no stream and returns 0
without EOF, so nghttp2 sends empty DATA frames until OOM. Both
client and server streams are affected.

Send the deferred RST_STREAM in _destroy(). As a backstop, return
NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE from OnRead when the stream is
gone, which nghttp2 documents as the way to reset a stream on error.

Fixes: nodejs#67363
Signed-off-by: inoway46 <inoueyuya416@gmail.com>
@codecov

codecov Bot commented Nov 10, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 94.11765% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 90.71%. Comparing base (2929073) to head (7288a16).

Files with missing lines Patch % Lines
src/node_http2.cc 0.00% 0 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main   #67372      +/-   ##
==========================================
- Coverage   92.62%   90.71%   -1.91%     
==========================================
  Files         430      798     +368     
  Lines      196333   280032   +83699     
  Branches    29897    53860   +23963     
==========================================
+ Hits       181849   254038   +72189     
- Misses      14159    16283    +2124     
- Partials      325     9711    +9386     
Files with missing lines Coverage Δ
lib/internal/http2/core.js 94.94% <100.00%> (+0.14%) ⬆️
src/node_http2.cc 82.02% <0.00%> (ø)

... and 508 files with indirect coverage changes

🚀 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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

c++ Issues and PRs that require attention from people who are familiar with C++. http2 Issues and PRs related to the http2 subsystem. needs-ci PRs that need a full CI run.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

http2: closing and then destroying a client stream whose body is still queued sends no RST_STREAM and loops on empty DATA frames until OOM

2 participants