Skip to content

tls: destroy sockets after fatal errors - #67215

Open
inoway46 wants to merge 2 commits into
nodejs:mainfrom
inoway46:fix/http2-tls-fatal-cleanup
Open

inoway46 wants to merge 2 commits into
nodejs:mainfrom
inoway46:fix/http2-tls-fatal-cleanup

Conversation

@inoway46

@inoway46 inoway46 commented Nov 3, 2026 •

Copy link
Copy Markdown
Contributor

Destroy established TLS sockets on fatal TLS errors so pending writes cannot block HTTP/2 session cleanup. Preserve connection details during error handling using the existing _closeAfterHandlingError mechanism.

This requires fixing an existing crash in that mechanism: TLS frees its SSL state before emitting close, but the socket still exposes the handle to close listeners. Calling getProtocol() from a close listener after a failed handshake can therefore crash the process.

The first commit clears the closed handle before emitting close and adds a regression test. The second applies the TLS cleanup change and adds coverage for standalone TLS closure and HTTP/2 cleanup with default and custom connections.

Fixes: #67213

@nodejs-github-bot

Copy link
Copy Markdown
Collaborator

Review requested:

  • @nodejs/http2
  • @nodejs/net

@nodejs-github-bot nodejs-github-bot added http2 Issues and PRs related to the http2 subsystem. needs-ci PRs that need a full CI run. labels Nov 3, 2026
@inoway46
inoway46 marked this pull request as ready for review November 3, 2026 07:03
@codecov

codecov Bot commented Nov 3, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 90.67%. Comparing base (70074c6) to head (87ce55b).
⚠️ Report is 19 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main   #67215      +/-   ##
==========================================
- Coverage   90.71%   90.67%   -0.05%     
==========================================
  Files         797      797              
  Lines      278898   279370     +472     
  Branches    53627    53739     +112     
==========================================
+ Hits       252995   253309     +314     
- Misses      16269    16356      +87     
- Partials     9634     9705      +71     
Files with missing lines Coverage Δ
lib/internal/tls/wrap.js 95.67% <100.00%> (+<0.01%) ⬆️
lib/net.js 94.78% <100.00%> (+<0.01%) ⬆️

... and 33 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.

@inoway46

This comment was marked as outdated.

Comment thread lib/internal/http2/core.js Outdated
session.destroy(error);
// TLS errors reported by the native handle leave established sockets open.
// Cancel writes that cannot complete after a fatal TLS error.
if (this instanceof tls.TLSSocket && this._hadError)

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.

This looks like we have a bug somewhere else, it should not be need a special if here

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Thanks, I reproduced this with TLS alone and moved the fix there. TLS should close an unusable connection without relying on HTTP/2.

destroy(err) alone fixes the original issue. I used _closeAfterHandlingError to preserve connection details in error handlers, but that exposed an existing getProtocol() crash in close handlers. The first commit fixes that; the second adds the TLS cleanup.

@inoway46 inoway46 changed the title http2: destroy TLS sockets after fatal errors tls: destroy sockets after fatal errors Nov 4, 2026
@inoway46
inoway46 marked this pull request as draft November 4, 2026 13:24
Clear a deferred socket handle before invoking close listeners. TLS has
already freed its SSL state at this point, so retaining the handle lets
getProtocol() access a null SSL pointer and crash the process.

Keep connection details available during tlsClientError and add coverage
for querying the protocol after a failed handshake closes the socket.

Signed-off-by: inoway46 <inoueyuya416@gmail.com>
Assisted-by: Codex
Destroy established TLS sockets on fatal errors so pending writes
cannot prevent HTTP/2 session cleanup from completing. Defer closing
until after error handling to preserve connection details for listeners.

Add regression coverage for standalone TLS socket closure and HTTP/2
cleanup with default and custom TLS connections.

Fixes: nodejs#67213
Signed-off-by: inoway46 <inoueyuya416@gmail.com>
Assisted-by: Codex
@inoway46
inoway46 force-pushed the fix/http2-tls-fatal-cleanup branch from 5aaccbd to 87ce55b Compare November 4, 2026 13:30
@inoway46 inoway46 added the commit-queue-rebase PRs the Commit Queue should land as multiple self-contained commits. label Nov 4, 2026
@inoway46
inoway46 marked this pull request as ready for review November 4, 2026 13:32
@inoway46
inoway46 requested a review from mcollina November 4, 2026 15:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

commit-queue-rebase PRs the Commit Queue should land as multiple self-contained commits. 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: client session leaks (no 'error', no 'close', socket never destroyed) when the server rejects the TLS handshake

3 participants