Skip to content
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: avoid pause with unpipe in buffered write #2325

Closed
wants to merge 1 commit into from

Conversation

mscdex
Copy link
Contributor

@mscdex mscdex commented Aug 7, 2015

If a pipe is cleaned up (due to unpipe) during a failed write(),
the source stream can get stuck in a paused state.

Fixes: #2323

@mscdex mscdex added the stream Issues and PRs related to the stream subsystem. label Aug 7, 2015
@LinusU
Copy link
Contributor

LinusU commented Aug 14, 2015

@mscdex This fixes the problem, thank you so much, would love to see this landed 💯 👍

I'm currently using this as a workaround. Is it stupid as fuck or should it work?

function done (err) {
  if (isDone) return
  isDone = true

  req.unpipe(busboy)
  req.resume()
  busboy.removeAllListeners()

  /* Work around bug in Node.js
   * https://github.com/nodejs/node/issues/2323
   */
  setImmediate(function () {
    if (req._readableState.awaitDrain === 1) {
      req._readableState.awaitDrain--
      req.resume()
    }
  })

  onFinished(req, function () { next(err) })
}

I'm also having some trouble which forces me to add the onFinished part, it seems like I have to wait for all data to arrive before I can send data back... I'll try to investigate and open another issue.

Again, thank you for the quick help!

@mscdex
Copy link
Contributor Author

mscdex commented Aug 15, 2015

/cc @nodejs/streams

writer1.once('chunk-received', function() {
reader.unpipe(writer1);
reader.pipe(writer2);
reader.push(new Buffer(560000));
Copy link
Contributor

Choose a reason for hiding this comment

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

what's the significants of this number, is it being used to bust the buffer?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It was copied from the test case in #2323. I think the point though is to fill up the internal buffer to cause the write() to return false.

@LinusU
Copy link
Contributor

LinusU commented Aug 29, 2015

If someone could help me to find a workaround for earlier Node versions (preferably back to 0.10) that would be very much appreciated.

I've tried here: expressjs/multer#205

@mscdex
Copy link
Contributor Author

mscdex commented Sep 10, 2015

Ok, updated PR according to suggestions.

@Fishrock123
Copy link
Contributor

@mscdex mscdex force-pushed the fix-stream-regression branch 2 times, most recently from 9b13ecb to b879ce0 Compare October 11, 2015 16:03
@mscdex
Copy link
Contributor Author

mscdex commented Oct 11, 2015

updated to use common.mustCall() in the test.

CI: https://ci.nodejs.org/job/node-test-commit/799/
Looks like two of the Windows machines failed for different reasons. Not sure what's up with that.

Does this look good to land now?

@thefourtheye
Copy link
Contributor

There can be a comment which explains the importance of 56000 or link to this PR. LGTM.

If a pipe is cleaned up (due to unpipe) during a write that
returned false, the source stream can get stuck in a paused state.

Fixes: nodejs#2323
mscdex added a commit that referenced this pull request Oct 11, 2015
If a pipe is cleaned up (due to unpipe) during a write that
returned false, the source stream can get stuck in a paused state.

Fixes: #2323
PR-URL: #2325
Reviewed-By: Sakthipriyan Vairamani <thechargingvolcano@gmail.com>
@mscdex
Copy link
Contributor Author

mscdex commented Oct 11, 2015

Landed in 6899094.

@mscdex mscdex closed this Oct 11, 2015
Trott pushed a commit to Trott/io.js that referenced this pull request Oct 12, 2015
If a pipe is cleaned up (due to unpipe) during a write that
returned false, the source stream can get stuck in a paused state.

Fixes: nodejs#2323
PR-URL: nodejs#2325
Reviewed-By: Sakthipriyan Vairamani <thechargingvolcano@gmail.com>
@LinusU
Copy link
Contributor

LinusU commented Oct 12, 2015

Nice, thanks!

mscdex added a commit that referenced this pull request Oct 12, 2015
If a pipe is cleaned up (due to unpipe) during a write that
returned false, the source stream can get stuck in a paused state.

Fixes: #2323
PR-URL: #2325
Reviewed-By: Sakthipriyan Vairamani <thechargingvolcano@gmail.com>
@jasnell
Copy link
Member

jasnell commented Oct 12, 2015

Landed in v4.x in 7b9f78a

@omrilitov
Copy link

Is this fixed in v4.2.0?
It's listed on the commits but it got merged after 4.2.0 release

@mscdex mscdex changed the title stream: avoid pause with unpipe in failed write stream: avoid pause with unpipe in buffered write Oct 26, 2015
@mscdex
Copy link
Contributor Author

mscdex commented Oct 26, 2015

@omrilitov It's included in v4.2.0.

@mscdex mscdex deleted the fix-stream-regression branch December 17, 2015 18:20
addaleax added a commit to addaleax/node that referenced this pull request Apr 3, 2016
In 6899094 (nodejs#2325),
the conditions for increasing `readableState.awaitDrain` when
writing to a piping destination returns false were changed so
that they could not actually be met, effectively leaving
`readableState.awaitDrain` with a constant value of 0.

This patch changes the conditions to testing whether the
stream for which `.write()` returned false is still a piping
destination, which was likely the intention of the original
patch.

Fixes: nodejs#5820
jasnell pushed a commit that referenced this pull request Apr 12, 2016
In 6899094 (#2325),
the conditions for increasing `readableState.awaitDrain` when
writing to a piping destination returns false were changed so
that they could not actually be met, effectively leaving
`readableState.awaitDrain` with a constant value of 0.

This patch changes the conditions to testing whether the
stream for which `.write()` returned false is still a piping
destination, which was likely the intention of the original
patch.

Fixes: #5820
Fixes: #5257
PR-URL: #6023
Reviewed-By: Brian White <mscdex@mscdex.net>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
MylesBorins pushed a commit that referenced this pull request Apr 19, 2016
In 6899094 (#2325),
the conditions for increasing `readableState.awaitDrain` when
writing to a piping destination returns false were changed so
that they could not actually be met, effectively leaving
`readableState.awaitDrain` with a constant value of 0.

This patch changes the conditions to testing whether the
stream for which `.write()` returned false is still a piping
destination, which was likely the intention of the original
patch.

Fixes: #5820
Fixes: #5257
PR-URL: #6023
Reviewed-By: Brian White <mscdex@mscdex.net>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
MylesBorins pushed a commit that referenced this pull request Apr 20, 2016
In 6899094 (#2325),
the conditions for increasing `readableState.awaitDrain` when
writing to a piping destination returns false were changed so
that they could not actually be met, effectively leaving
`readableState.awaitDrain` with a constant value of 0.

This patch changes the conditions to testing whether the
stream for which `.write()` returned false is still a piping
destination, which was likely the intention of the original
patch.

Fixes: #5820
Fixes: #5257
PR-URL: #6023
Reviewed-By: Brian White <mscdex@mscdex.net>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
MylesBorins pushed a commit that referenced this pull request Apr 20, 2016
In 6899094 (#2325),
the conditions for increasing `readableState.awaitDrain` when
writing to a piping destination returns false were changed so
that they could not actually be met, effectively leaving
`readableState.awaitDrain` with a constant value of 0.

This patch changes the conditions to testing whether the
stream for which `.write()` returned false is still a piping
destination, which was likely the intention of the original
patch.

Fixes: #5820
Fixes: #5257
PR-URL: #6023
Reviewed-By: Brian White <mscdex@mscdex.net>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
jasnell pushed a commit that referenced this pull request Apr 26, 2016
In 6899094 (#2325),
the conditions for increasing `readableState.awaitDrain` when
writing to a piping destination returns false were changed so
that they could not actually be met, effectively leaving
`readableState.awaitDrain` with a constant value of 0.

This patch changes the conditions to testing whether the
stream for which `.write()` returned false is still a piping
destination, which was likely the intention of the original
patch.

Fixes: #5820
Fixes: #5257
PR-URL: #6023
Reviewed-By: Brian White <mscdex@mscdex.net>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
MylesBorins pushed a commit that referenced this pull request Apr 30, 2016
In 6899094 (#2325),
the conditions for increasing `readableState.awaitDrain` when
writing to a piping destination returns false were changed so
that they could not actually be met, effectively leaving
`readableState.awaitDrain` with a constant value of 0.

This patch changes the conditions to testing whether the
stream for which `.write()` returned false is still a piping
destination, which was likely the intention of the original
patch.

Fixes: #5820
Fixes: #5257
PR-URL: #6023
Reviewed-By: Brian White <mscdex@mscdex.net>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
MylesBorins pushed a commit that referenced this pull request May 6, 2016
In 6899094 (#2325),
the conditions for increasing `readableState.awaitDrain` when
writing to a piping destination returns false were changed so
that they could not actually be met, effectively leaving
`readableState.awaitDrain` with a constant value of 0.

This patch changes the conditions to testing whether the
stream for which `.write()` returned false is still a piping
destination, which was likely the intention of the original
patch.

Fixes: #5820
Fixes: #5257
PR-URL: #6023
Reviewed-By: Brian White <mscdex@mscdex.net>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
MylesBorins pushed a commit that referenced this pull request May 18, 2016
In 6899094 (#2325),
the conditions for increasing `readableState.awaitDrain` when
writing to a piping destination returns false were changed so
that they could not actually be met, effectively leaving
`readableState.awaitDrain` with a constant value of 0.

This patch changes the conditions to testing whether the
stream for which `.write()` returned false is still a piping
destination, which was likely the intention of the original
patch.

Fixes: #5820
Fixes: #5257
PR-URL: #6023
Reviewed-By: Brian White <mscdex@mscdex.net>
Reviewed-By: Matteo Collina <matteo.collina@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
stream Issues and PRs related to the stream subsystem.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants