Skip to content

stream: fix Writable.toWeb() hang on synchronous drain#61197

Merged
nodejs-github-bot merged 1 commit into
nodejs:mainfrom
Han5991:fix/61145-stream-to-web-hang
May 22, 2026
Merged

stream: fix Writable.toWeb() hang on synchronous drain#61197
nodejs-github-bot merged 1 commit into
nodejs:mainfrom
Han5991:fix/61145-stream-to-web-hang

Conversation

@Han5991
Copy link
Copy Markdown
Contributor

@Han5991 Han5991 commented Dec 29, 2025

This PR fixes a race condition in Writable.toWeb() where the resulting WritableStream would hang if the underlying Node.js
Writable emitted the 'drain' event synchronously during a write() call.

This issue typically manifests when highWaterMark is set to 0, or in custom stream implementations that do not defer 'drain'
emissions. In such cases, the 'drain' event could fire before the adapter had a chance to set up the backpressurePromise and the
listener, causing the adapter to wait indefinitely for an event that had already occurred.

The fix involves checking streamWritable.writableNeedDrain immediately after write() returns false. If the stream is already
drained (i.e., writableNeedDrain is false), the backpressure promise is resolved immediately.

Related Issue

Fixes: #61145

image

@nodejs-github-bot nodejs-github-bot added needs-ci PRs that need a full CI run. web streams labels Dec 29, 2025
@codecov
Copy link
Copy Markdown

codecov Bot commented Dec 29, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 90.04%. Comparing base (0e8fb91) to head (db7eab3).
⚠️ Report is 47 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main   #61197      +/-   ##
==========================================
- Coverage   90.06%   90.04%   -0.02%     
==========================================
  Files         714      714              
  Lines      225918   225921       +3     
  Branches    42735    42744       +9     
==========================================
- Hits       203471   203434      -37     
- Misses      14232    14276      +44     
+ Partials     8215     8211       -4     
Files with missing lines Coverage Δ
lib/internal/webstreams/adapters.js 86.56% <100.00%> (+0.03%) ⬆️

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

@VoltrexKeyva VoltrexKeyva added the request-ci Add this label to start a Jenkins CI on a PR. label Dec 30, 2025
@github-actions github-actions Bot added request-ci-failed An error occurred while starting CI via request-ci label, and manual interventon is needed. and removed request-ci Add this label to start a Jenkins CI on a PR. labels Dec 30, 2025
@github-actions
Copy link
Copy Markdown
Contributor

Failed to start CI
   ⚠  No approving reviews found
   ✘  Refusing to run CI on potentially unsafe PR
https://github.com/nodejs/node/actions/runs/20606939876

@Han5991 Han5991 force-pushed the fix/61145-stream-to-web-hang branch from 1e7c128 to ec84fd4 Compare January 17, 2026 07:16
@Han5991 Han5991 force-pushed the fix/61145-stream-to-web-hang branch from ec84fd4 to 6fc9709 Compare March 28, 2026 13:25
@trivikr trivikr force-pushed the fix/61145-stream-to-web-hang branch from 6fc9709 to d1c83ac Compare May 20, 2026 03:53
@trivikr
Copy link
Copy Markdown
Member

trivikr commented May 20, 2026

@Han5991 I rebased you branch from main, but you need to sign your commit as per guidelines.

Can you check out the latest branch, and run:

  • git commit -s --amend --no-edit
  • git push --force-with-lease?

A race condition in the Writable.toWeb() adapter caused the stream
to hang if the underlying Node.js Writable emitted a 'drain' event
synchronously during a write() call. This often happened when
highWaterMark was set to 0.

By checking writableNeedDrain immediately after a backpressured write,
the adapter now correctly detects if the stream has already drained,
resolving the backpressure promise instead of waiting indefinitely
for an event that has already occurred.

Fixes: nodejs#61145
Signed-off-by: sangwook <rewq5991@gmail.com>
@Han5991 Han5991 force-pushed the fix/61145-stream-to-web-hang branch from d1c83ac to db7eab3 Compare May 20, 2026 09:33
@Han5991
Copy link
Copy Markdown
Contributor Author

Han5991 commented May 20, 2026

  • git commit -s --amend --no-edit

@trivikr

Thanks for letting me know!

@trivikr trivikr added request-ci Add this label to start a Jenkins CI on a PR. and removed request-ci-failed An error occurred while starting CI via request-ci label, and manual interventon is needed. labels May 21, 2026
@github-actions github-actions Bot removed the request-ci Add this label to start a Jenkins CI on a PR. label May 21, 2026
@nodejs-github-bot
Copy link
Copy Markdown
Collaborator

@trivikr

This comment was marked as outdated.

@trivikr trivikr added the commit-queue Add this label to land a pull request using GitHub Actions. label May 22, 2026
@nodejs-github-bot nodejs-github-bot removed the commit-queue Add this label to land a pull request using GitHub Actions. label May 22, 2026
@nodejs-github-bot nodejs-github-bot merged commit 7e7bde8 into nodejs:main May 22, 2026
73 checks passed
@nodejs-github-bot
Copy link
Copy Markdown
Collaborator

Landed in 7e7bde8

aduh95 pushed a commit that referenced this pull request May 22, 2026
A race condition in the Writable.toWeb() adapter caused the stream
to hang if the underlying Node.js Writable emitted a 'drain' event
synchronously during a write() call. This often happened when
highWaterMark was set to 0.

By checking writableNeedDrain immediately after a backpressured write,
the adapter now correctly detects if the stream has already drained,
resolving the backpressure promise instead of waiting indefinitely
for an event that has already occurred.

Fixes: #61145
Signed-off-by: sangwook <rewq5991@gmail.com>
PR-URL: #61197
Reviewed-By: Trivikram Kamat <trivikr.dev@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

needs-ci PRs that need a full CI run. web streams

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Stream created by Writable.toWeb() hangs when highWaterMark is set to 0

5 participants