-
Notifications
You must be signed in to change notification settings - Fork 29.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
stream: reset awaitDrain after manual .resume() #7160
Conversation
Reset the `readableState.awaitDrain` counter after manual calls to `.resume()`. What might happen otherwise is that a slow consumer at the end of the pipe could end up stalling the piping in the following scenario: 1. The writable stream indicates that its buffer is full. 2. This leads the readable stream to `pause()` and increase its `awaitDrain` counter, which will be decreased by the writable’s next `drain` event. 3. Something calls `.resume()` manually. 4. The readable continues to pipe to the writable, but once again the writable stream indicates that the buffer is full. 5. The `awaitDrain` counter is thus increased again, but since it has now been increased twice for a single piping destination, the next `drain` event will not be able to reset `awaitDrain` to zero. 6. The pipe is stalled and no data is passed along anymore. The solution in this commit is to reset the `awaitDrain` counter to zero when `resume()` is called. Fixes: nodejs#7159
I think this should be ok to backport, but we should probably check CIGTM before that. cc @calvinmetcalf LGTM |
LGTM if @nodejs/streams folks are happy. |
@thealphanerd since you self-assigned this… anything in particular you’d like to see before landing? |
Doesn't look to be anything to controversial from my perspective |
@calvinmetcalf I'm assuming you did not mean to close this 😄 |
@addaleax Nothing I need to see before landing, assigned to myself to keep an eye on it for LTS |
@thealphanerd you are correct sorry foks |
as long as @mcollina is happy i'm happy so 👍 |
Reset the `readableState.awaitDrain` counter after manual calls to `.resume()`. What might happen otherwise is that a slow consumer at the end of the pipe could end up stalling the piping in the following scenario: 1. The writable stream indicates that its buffer is full. 2. This leads the readable stream to `pause()` and increase its `awaitDrain` counter, which will be decreased by the writable’s next `drain` event. 3. Something calls `.resume()` manually. 4. The readable continues to pipe to the writable, but once again the writable stream indicates that the buffer is full. 5. The `awaitDrain` counter is thus increased again, but since it has now been increased twice for a single piping destination, the next `drain` event will not be able to reset `awaitDrain` to zero. 6. The pipe is stalled and no data is passed along anymore. The solution in this commit is to reset the `awaitDrain` counter to zero when `resume()` is called. Fixes: #7159 PR-URL: #7160 Reviewed-By: Matteo Collina <[email protected]> Reviewed-By: James M Snell <[email protected]>
Landed in e2e615e, thanks for the reviews and comments, everyone! |
Reset the `readableState.awaitDrain` counter after manual calls to `.resume()`. What might happen otherwise is that a slow consumer at the end of the pipe could end up stalling the piping in the following scenario: 1. The writable stream indicates that its buffer is full. 2. This leads the readable stream to `pause()` and increase its `awaitDrain` counter, which will be decreased by the writable’s next `drain` event. 3. Something calls `.resume()` manually. 4. The readable continues to pipe to the writable, but once again the writable stream indicates that the buffer is full. 5. The `awaitDrain` counter is thus increased again, but since it has now been increased twice for a single piping destination, the next `drain` event will not be able to reset `awaitDrain` to zero. 6. The pipe is stalled and no data is passed along anymore. The solution in this commit is to reset the `awaitDrain` counter to zero when `resume()` is called. Fixes: #7159 PR-URL: #7160 Reviewed-By: Matteo Collina <[email protected]> Reviewed-By: James M Snell <[email protected]>
fixes streams error nodejs/node#7160
fixes streams error nodejs/node#7160
Reset the `readableState.awaitDrain` counter after manual calls to `.resume()`. What might happen otherwise is that a slow consumer at the end of the pipe could end up stalling the piping in the following scenario: 1. The writable stream indicates that its buffer is full. 2. This leads the readable stream to `pause()` and increase its `awaitDrain` counter, which will be decreased by the writable’s next `drain` event. 3. Something calls `.resume()` manually. 4. The readable continues to pipe to the writable, but once again the writable stream indicates that the buffer is full. 5. The `awaitDrain` counter is thus increased again, but since it has now been increased twice for a single piping destination, the next `drain` event will not be able to reset `awaitDrain` to zero. 6. The pipe is stalled and no data is passed along anymore. The solution in this commit is to reset the `awaitDrain` counter to zero when `resume()` is called. Fixes: #7159 PR-URL: #7160 Reviewed-By: Matteo Collina <[email protected]> Reviewed-By: James M Snell <[email protected]>
Reset the `readableState.awaitDrain` counter after manual calls to `.resume()`. What might happen otherwise is that a slow consumer at the end of the pipe could end up stalling the piping in the following scenario: 1. The writable stream indicates that its buffer is full. 2. This leads the readable stream to `pause()` and increase its `awaitDrain` counter, which will be decreased by the writable’s next `drain` event. 3. Something calls `.resume()` manually. 4. The readable continues to pipe to the writable, but once again the writable stream indicates that the buffer is full. 5. The `awaitDrain` counter is thus increased again, but since it has now been increased twice for a single piping destination, the next `drain` event will not be able to reset `awaitDrain` to zero. 6. The pipe is stalled and no data is passed along anymore. The solution in this commit is to reset the `awaitDrain` counter to zero when `resume()` is called. Fixes: #7159 PR-URL: #7160 Reviewed-By: Matteo Collina <[email protected]> Reviewed-By: James M Snell <[email protected]>
Reset the `readableState.awaitDrain` counter after manual calls to `.resume()`. What might happen otherwise is that a slow consumer at the end of the pipe could end up stalling the piping in the following scenario: 1. The writable stream indicates that its buffer is full. 2. This leads the readable stream to `pause()` and increase its `awaitDrain` counter, which will be decreased by the writable’s next `drain` event. 3. Something calls `.resume()` manually. 4. The readable continues to pipe to the writable, but once again the writable stream indicates that the buffer is full. 5. The `awaitDrain` counter is thus increased again, but since it has now been increased twice for a single piping destination, the next `drain` event will not be able to reset `awaitDrain` to zero. 6. The pipe is stalled and no data is passed along anymore. The solution in this commit is to reset the `awaitDrain` counter to zero when `resume()` is called. Fixes: #7159 PR-URL: #7160 Reviewed-By: Matteo Collina <[email protected]> Reviewed-By: James M Snell <[email protected]>
This LTS release comes with 89 commits. This includes 46 commits that are docs related, 11 commits that are test related, 8 commits that are build related, and 4 commits that are benchmark related. Notable Changes: - debugger: - All properties of an array (aside from length) can now be printed in the repl (cjihrig) #6448 - npm: - Upgrade npm to 2.15.8 (Rebecca Turner) #7412 - stream: - Fix for a bug that became more prevalent with the stream changes that landed in v4.4.5. (Anna Henningsen) #7160 - V8: - Fix for a bug in crankshaft that was causing crashes on arm64 (Myles Borins) #7442 - Add missing classes to postmortem info such as JSMap and JSSet (evan.lucas) #3792
This LTS release comes with 89 commits. This includes 46 commits that are docs related, 11 commits that are test related, 8 commits that are build related, and 4 commits that are benchmark related. Notable Changes: - debugger: - All properties of an array (aside from length) can now be printed in the repl (cjihrig) #6448 - npm: - Upgrade npm to 2.15.8 (Rebecca Turner) #7412 - stream: - Fix for a bug that became more prevalent with the stream changes that landed in v4.4.5. (Anna Henningsen) #7160 - V8: - Fix for a bug in crankshaft that was causing crashes on arm64 (Myles Borins) #7442 - Add missing classes to postmortem info such as JSMap and JSSet (evan.lucas) #3792
Checklist
Affected core subsystem(s)
stream
Description of change
Reset the
readableState.awaitDrain
counter after manual calls to.resume()
.What might happen otherwise is that a slow consumer at the end of the pipe could end up stalling the piping in the following scenario:
pause()
and increase itsawaitDrain
counter, which will be decreased by the writable’s nextdrain
event..resume()
manually.awaitDrain
counter is thus increased again, but since it has now been increased twice for a single piping destination, the nextdrain
event will not be able to resetawaitDrain
to zero.The solution in this commit is to reset the
awaitDrain
counter to zero whenresume()
is called.Fixes: #7159
This bug is has been around at least since 0.12, and I don’t currently know why it never popped up before #2325 when the
awaitDrain
mechanism worked like it does today./cc @nodejs/streams