-
Notifications
You must be signed in to change notification settings - Fork 29.6k
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: fix not calling cleanup() when unpiping all streams. #18266
Conversation
lib/_stream_readable.js
Outdated
@@ -758,8 +758,10 @@ Readable.prototype.unpipe = function(dest) { | |||
state.pipesCount = 0; | |||
state.flowing = false; | |||
|
|||
for (var i = 0; i < len; i++) | |||
for (var i = 0; i < len; i++) { | |||
unpipeInfo = { hasUnpiped: 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.
For other reviewers, we need a new object becausedest
sets unpipeInfo.hasUnpiped
to true
when 'unpipe'
is emitted.
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.
On second thought, doesn't this make the hasUnpiped
guard useless? I mean, no matter what, dest
will always find hasUnpiped
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.
I found the PR which adds the hasUnpiped
. you can see it.
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.
@lpinca hasUnpiped
solved the situation that a readable stram piped the same writable stream more than one time. This change has no influence to it.
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.
Ok yes, it seems correct as this is for the "remove all" case.
lib/_stream_readable.js
Outdated
@@ -758,8 +758,10 @@ Readable.prototype.unpipe = function(dest) { | |||
state.pipesCount = 0; | |||
state.flowing = false; | |||
|
|||
for (var i = 0; i < len; i++) | |||
for (var i = 0; i < len; i++) { | |||
unpipeInfo = { hasUnpiped: false }; | |||
dests[i].emit('unpipe', this, unpipeInfo); |
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.
Tiny nit: I'd just create the new object here, without using the above assignment.
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.
There are three situations to use unpipeInfo
. The above assignment can be used in two situations. I’m also fine to assign it just before using it.
lib/_stream_readable.js
Outdated
@@ -758,8 +758,12 @@ Readable.prototype.unpipe = function(dest) { | |||
state.pipesCount = 0; | |||
state.flowing = false; | |||
|
|||
for (var i = 0; i < len; i++) | |||
// use the above assignment | |||
dests[0].emit('unpipe', this, unpipeInfo); |
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.
What I meant in my previous comment was:
for (var i = 0; i < len; i++)
dests[i].emit('unpipe', this, { hasUnpiped: 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.
ok~
08153b1
to
3500d5f
Compare
/cc @nodejs/streams |
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.
The fix here seems good although I would prefer a test that accounts for more stuff within cleanup()
.
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.
LGTM
@apapirovski I added more test contents. |
|
||
const unpipeChecker = common.mustCall(() => { | ||
assert.strictEqual( | ||
dest.listenerCount('unpipe'), 1, |
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.
Nit: I'd simplify this as
assert.deepStrictEqual(dest.listeners('unpipe'), [unpipeChecker]);
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.
ok~
srcCheckEventNames.forEach((eventName) => { | ||
assert.strictEqual( | ||
source.listenerCount(eventName), 0, | ||
`source's '${eventName}' event listeners don't be cleaned up` |
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.
Nit: replace "don't be cleaned up" with "not removed", same below.
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.
ok~
@MoonBall I think with this we can remove |
This PR makes sure the object emitted as the 'unpipe' event in the destination stream is not shared between destination, as it would be muted. Refs: #12746 PR-URL: #18266 Reviewed-By: Luigi Pinca <luigipinca@gmail.com> Reviewed-By: Anatoli Papirovski <apapirovski@mac.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de> Reviewed-By: Anna Henningsen <anna@addaleax.net>
Landed as a52b7a2. |
This PR makes sure the object emitted as the 'unpipe' event in the destination stream is not shared between destination, as it would be muted. Refs: #12746 PR-URL: #18266 Reviewed-By: Luigi Pinca <luigipinca@gmail.com> Reviewed-By: Anatoli Papirovski <apapirovski@mac.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de> Reviewed-By: Anna Henningsen <anna@addaleax.net>
This PR makes sure the object emitted as the 'unpipe' event in the destination stream is not shared between destination, as it would be muted. Refs: #12746 PR-URL: #18266 Reviewed-By: Luigi Pinca <luigipinca@gmail.com> Reviewed-By: Anatoli Papirovski <apapirovski@mac.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de> Reviewed-By: Anna Henningsen <anna@addaleax.net>
Refs: #12746
After a readable stream pipes more than one writable streams, I calls
readable.unpipe()
to remove all piped writable stream. I find that only the first piped writable stream calls thecleanup()
, the others don't callcleanup()
.Checklist
make -j4 test
(UNIX), orvcbuild test
(Windows) passesAffected core subsystem(s)
stream