-
Notifications
You must be signed in to change notification settings - Fork 30k
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: only increase awaitDrain once for each pipe destination #7292
Conversation
cb(); | ||
}, 3); | ||
|
||
const pthru = new stream.PassThrough(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just curious, would a Readable
suffice here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, but I'd have to set its _read
to a nullop.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess I could try doing the push
s in the _read
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You could use new stream.Readable({read: () => {}})
, but you can just leave it as a PassThrough
if you prefer, I really was just curious. :)
Thanks, generally looking good! If you want, you can add an |
@addaleax thanks for the review. I'll add a commit addressing your comments but it won't be today now. |
okay I just updated the test |
write: common.mustCall((chunk, encoding, cb) => { | ||
if (chunk.length === 32 * 1024) { // first chunk | ||
readable.push(new Buffer(33 * 1024)); // above hwm | ||
return process.nextTick(cb); // let pipe increment awaitDrain |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this line actually necessary? I think the test still tests what it’s supposed to test if you leave it out, because after the push()
call here awaitDrain
would already be 2
… right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wanted to test the effect (missing third buffer) rather than the cause.
In any case, awaitDrain
isn't incremented until _write
returns so it won't already be 2.
/cc @nodejs/streams I’d be kind of interested in knowing whether we generally guarantee that |
Also, I’m not sure why, but this branch seems to be based on a |
If |
No idea why it's a month old - only forked it yesterday. |
This branch is now rebased on latest |
@addaleax I removed the |
@@ -550,10 +550,12 @@ Readable.prototype.pipe = function(dest, pipeOpts) { | |||
} | |||
|
|||
src.on('data', ondata); | |||
var increasedAwaitDrain = false; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can you please add a comment on the reason for this variable?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
also we probably wanna move up the declaration of increasedAwaitDrain
to before the ondata
handler is attached. i'm pretty sure that might fire sync in some cases
Can you please format the commit message and squash the commits? |
This bug is "fixed" from |
Guard against the call to write() inside pipe's ondata pushing more data back onto the Readable, thus causing ondata to be called again. This is fine but results in awaitDrain being increased more than once. The problem with that is when the destination does drain, only a single 'drain' event is emitted, so awaitDrain in this case will never reach zero and we end up with a permanently paused stream.
@addaleax exactly. That means if you are depending on readable-stream@~2.0 it's fixed, and broken in readable-stream@~2.1 and readable-stream@^2.1. (I thought good first contribution was to tag possible future contributors, maybe I got it wrong) |
Should be squashed and reformatted now. |
LGTM |
CI: https://ci.nodejs.org/job/node-test-commit/3753/ |
LGTM |
Landed in b5175e8 Thanks for fixing this bug, @davedoesdev! I believe this is your first commit to core, if so, welcome on board and we hope you find other ways to contribute! |
Guard against the call to write() inside pipe's ondata pushing more data back onto the Readable, thus causing ondata to be called again. This is fine but results in awaitDrain being increased more than once. The problem with that is when the destination does drain, only a single 'drain' event is emitted, so awaitDrain in this case will never reach zero and we end up with a permanently paused stream. Fixes: #7278 PR-URL: #7292 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Anna Henningsen <anna@addaleax.net>
Guard against the call to write() inside pipe's ondata pushing more data back onto the Readable, thus causing ondata to be called again. This is fine but results in awaitDrain being increased more than once. The problem with that is when the destination does drain, only a single 'drain' event is emitted, so awaitDrain in this case will never reach zero and we end up with a permanently paused stream. Fixes: #7278 PR-URL: #7292 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Anna Henningsen <anna@addaleax.net>
// A readable stream which produces two buffers. | ||
const bufs = [new Buffer(32 * 1024), new Buffer(33 * 1024)]; // above hwm | ||
const readable = new stream.Readable({ | ||
read: function() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
could have been read() {
^_^
Guard against the call to write() inside pipe's ondata pushing more data back onto the Readable, thus causing ondata to be called again. This is fine but results in awaitDrain being increased more than once. The problem with that is when the destination does drain, only a single 'drain' event is emitted, so awaitDrain in this case will never reach zero and we end up with a permanently paused stream. Fixes: #7278 PR-URL: #7292 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Anna Henningsen <anna@addaleax.net>
Guard against the call to write() inside pipe's ondata pushing more data back onto the Readable, thus causing ondata to be called again. This is fine but results in awaitDrain being increased more than once. The problem with that is when the destination does drain, only a single 'drain' event is emitted, so awaitDrain in this case will never reach zero and we end up with a permanently paused stream. Fixes: #7278 PR-URL: #7292 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Anna Henningsen <anna@addaleax.net>
Guard against the call to write() inside pipe's ondata pushing more data back onto the Readable, thus causing ondata to be called again. This is fine but results in awaitDrain being increased more than once. The problem with that is when the destination does drain, only a single 'drain' event is emitted, so awaitDrain in this case will never reach zero and we end up with a permanently paused stream. Fixes: #7278 PR-URL: #7292 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Anna Henningsen <anna@addaleax.net>
Checklist
make -j4 test
(UNIX) orvcbuild test nosign
(Windows) passesAffected core subsystem(s)
stream
Description of change
Guard against the call to
write()
inside pipe'sondata
pushing more databack onto the
Readable
, thus causingondata
to be called again.This is fine but results in
awaitDrain
being increased more than once.The problem with that is when the destination does drain, only a single
drain
event is emitted, so
awaitDrain
in this case will never reach zero and weend up with a permanently paused stream.
#7278