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

streams: support unlimited synchronous cork/uncork cycles #6164

Closed
wants to merge 1 commit into from

Conversation

mcollina
Copy link
Member

Checklist
  • tests and code linting passes
  • a test and/or benchmark is included
Affected core subsystem(s)

streams, writable

Description of change

net streams can request multiple chunks to be written in a synchronous
fashion. If this is combined with cork/uncork, en error is currently
thrown because of a regression introduced in:
89aeab9
(#4354).

I am not creating a full linked list anyway, because that is not needed in any "normal" operation of the stream, and I think multiple cork/uncork synchronously it is a very edge case: we can possibly waste some objects and callbacks.
Just to clarify, we are supporting a "feature" that can easily lead to event loop starvation and memory leaks, because for each synchronous cork/uncork cycle, we are adding a task in the nextTick queue:

process.nextTick(afterWrite, stream, state, finished, cb);
.

Fixes: #6154.

@mcollina mcollina added stream Issues and PRs related to the stream subsystem. lts-watch-v4.x labels Apr 12, 2016
@mcollina
Copy link
Member Author

@jfhbrook are you able to test this?

@mcollina
Copy link
Member Author

cc @nodejs/streams please review asap.

@thealphanerd you might want to include this one for #6149.

@@ -387,12 +387,17 @@ function clearBuffer(stream, state) {

doWrite(stream, state, true, state.length, buffer, '', holder.finish);

// doWrite is always async, defer these to save a bit of time
// doWrite is almost always async, defer these to save a bit of time
// as the hot path ends with doWrite
state.pendingcb++;
state.lastBufferedRequest = null;
state.corkedRequestsFree = holder.next;
Copy link
Contributor

Choose a reason for hiding this comment

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

probably want to remove this line as well

@mafintosh
Copy link
Member

Other than @calvinmetcalf's comment this is LGTM from em

net streams can request multiple chunks to be written in a synchronous
fashion. If this is combined with cork/uncork, en error is currently
thrown because of a regression introduced in:
nodejs@89aeab9
(nodejs#4354).

Fixes: nodejs#6154.
@mcollina
Copy link
Member Author

I have updated it, mainly cleaning things up. Let me know what you think cc @mafintosh @calvinmetcalf.

@mcollina
Copy link
Member Author

@mcollina
Copy link
Member Author

(how do I launch CITGM?)

@mscdex
Copy link
Contributor

mscdex commented Apr 12, 2016

@mcollina The thealphanerd-smoker task. Started one here: https://ci.nodejs.org/job/thealphanerd-smoker/195/

@mcollina
Copy link
Member Author

Another CI: https://ci.nodejs.org/job/node-test-pull-request/2247 (previous one missing the "safe" flag).

@mcollina
Copy link
Member Author

@jfhbrook
Copy link
Contributor

@jfhbrook are you able to test this?

A little hard because we're only seeing this in production, but I'll see what we can do.

@mcollina
Copy link
Member Author

CIGTM passes.

@mcollina mcollina mentioned this pull request Apr 12, 2016
@MylesBorins
Copy link
Contributor

How long will it take for this to land in v5?

@mcollina
Copy link
Member Author

Done for me, awaiting LGTMs. CI and CIGTM passes. Today or tomorrow I presume.

res = conn.write(buf);
conn.uncork();
}
assert.equal(i, N);
Copy link
Member

Choose a reason for hiding this comment

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

maybe also assert res is still true, since it could have been false in the last iteration.

Copy link
Member Author

Choose a reason for hiding this comment

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

You are right, it's not really an assert on that. I was also afraid of putting the assert in i, as it could be spurious (it depends on OS buffers and the like). I would avoid to stretching luck, I picked 100 as a random number that was working on my box.

Copy link
Member

Choose a reason for hiding this comment

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

100 seems reasonable, a comment there would be nice but I guess it's pretty straightforward as is.

@benjamingr
Copy link
Member

LGTM, nice fix.

@jfhbrook
Copy link
Contributor

How long will it take for this to land in v5?

More importantly, v4?

@benjamingr
Copy link
Member

@jfhbrook typically pull requests wait for 2 days before being landed so all collaborators have a chance to look at them. After that the road to v4 and v5 is usually very fast. The fix is good and it has already been LGTMd by 2 collaborators so it shouldn't be more than 2 days unless new information is discovered. Of course - in cases of urgency pull requests might be merged sooner, and also - you can always take the changes here - apply them to the v4 branch and build it if you need this fix faster than that.

@mcollina
Copy link
Member Author

If there aren't any other concern, I would merge it on Thursday morning (CEST).

@mafintosh
Copy link
Member

@mcollina LGTM

@mafintosh
Copy link
Member

@mcollina also great job on the fast turn around!

@jasnell
Copy link
Member

jasnell commented Apr 13, 2016

LGTM

@jfhbrook
Copy link
Contributor

@mcollina just a heads up, we are in fact floating this patch in prod right now, so far no breakage \o/

This is expected to land in 4.4.4 right? Just trying to track the work around not having to float patches anymore :)

@benjamingr
Copy link
Member

@jfhbrook if you're eager and want to help you're welcome to open a pull request backporting this patch against the v4-staging branch. Contributions are always welcome.

@jfhbrook
Copy link
Contributor

Sure. Would that be helpful? Like in our case I just did a cherry-pick

MylesBorins pushed a commit that referenced this pull request Apr 19, 2016
net streams can request multiple chunks to be written in a synchronous
fashion. If this is combined with cork/uncork, en error is currently
thrown because of a regression introduced in:
89aeab9
(#4354).

Fixes: #6154
PR-URL: #6164
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
Reviewed-By: Mathias Buus <mathiasbuus@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
MylesBorins pushed a commit that referenced this pull request Apr 20, 2016
net streams can request multiple chunks to be written in a synchronous
fashion. If this is combined with cork/uncork, en error is currently
thrown because of a regression introduced in:
89aeab9
(#4354).

Fixes: #6154
PR-URL: #6164
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
Reviewed-By: Mathias Buus <mathiasbuus@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
@MylesBorins MylesBorins mentioned this pull request Apr 20, 2016
MylesBorins pushed a commit that referenced this pull request Apr 20, 2016
net streams can request multiple chunks to be written in a synchronous
fashion. If this is combined with cork/uncork, en error is currently
thrown because of a regression introduced in:
89aeab9
(#4354).

Fixes: #6154
PR-URL: #6164
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
Reviewed-By: Mathias Buus <mathiasbuus@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
MylesBorins pushed a commit that referenced this pull request Apr 21, 2016
Buffer:
  * Buffer.prototype.compare can now compare sub-ranges of two Buffers
   (James M Snell) #5880

deps:
  * update to http-parser 2.7.0
    (Fedor Indutny) #6279
  * update ESLint to 2.7.0
    (silverwind) #6132

net:
  * adds support for passing DNS lookup hints to createConnection()
    (Colin Ihrig) #6000

node:
  * Make the builtin libraries available for the --eval and --print
    CLI options
    (Anna Henningsen) #6207

npm:
  * upgrade npm to 3.8.6
    (Kat Marchán) #6153

repl:
  * Pressing enter in the repl will repeat the last command by default
    if no input has been received. This behaviour was in node
    previously and was not removed intentionally.
    (Rich Trott) #6090

src:
  * add SIGINFO to supported signals
    (James Reggio) #6093

streams:
  * Fix a regression that caused by net streams requesting multiple
    chunks synchronously when combined with cork/uncork
    (Matteo Collina) #6164

zlib:
  * The flushing flag is now configurable allowing for decompression
    of partial data
    (Anna Henningsen) #6069
This was referenced Apr 21, 2016
MylesBorins pushed a commit that referenced this pull request Apr 21, 2016
Buffer:
  * Buffer.prototype.compare can now compare sub-ranges of two Buffers
   (James M Snell) #5880

deps:
  * update to http-parser 2.7.0
    (Fedor Indutny) #6279
  * update ESLint to 2.7.0
    (silverwind) #6132

net:
  * adds support for passing DNS lookup hints to createConnection()
    (Colin Ihrig) #6000

node:
  * Make the builtin libraries available for the --eval and --print
    CLI options
    (Anna Henningsen) #6207

npm:
  * upgrade npm to 3.8.6
    (Kat Marchán) #6153

repl:
  * Pressing enter in the repl will repeat the last command by default
    if no input has been received. This behavior was in node
    previously and was not removed intentionally.
    (Rich Trott) #6090

src:
  * add SIGINFO to supported signals
    (James Reggio) #6093

streams:
  * Fix a regression that caused by net streams requesting multiple
    chunks synchronously when combined with cork/uncork
    (Matteo Collina) #6164

zlib:
  * The flushing flag is now configurable allowing for decompression
    of partial data
    (Anna Henningsen) #6069
MylesBorins pushed a commit that referenced this pull request Apr 21, 2016
Buffer:
  * Buffer.prototype.compare can now compare sub-ranges of two Buffers
   (James M Snell) #5880

deps:
  * update to http-parser 2.7.0
    (Fedor Indutny) #6279
  * update ESLint to 2.7.0
    (silverwind) #6132

net:
  * adds support for passing DNS lookup hints to createConnection()
    (Colin Ihrig) #6000

node:
  * Make the builtin libraries available for the --eval and --print
    CLI options
    (Anna Henningsen) #6207

npm:
  * upgrade npm to 3.8.6
    (Kat Marchán) #6153

repl:
  * Pressing enter in the repl will repeat the last command by default
    if no input has been received. This behaviour was in node
    previously and was not removed intentionally.
    (Rich Trott) #6090

src:
  * add SIGINFO to supported signals
    (James Reggio) #6093

streams:
  * Fix a regression that caused by net streams requesting multiple
    chunks synchronously when combined with cork/uncork
    (Matteo Collina) #6164

zlib:
  * The flushing flag is now configurable allowing for decompression
    of partial data
    (Anna Henningsen) #6069

PR-URL: #6322
MylesBorins pushed a commit that referenced this pull request Apr 21, 2016
Buffer:
  * Buffer.prototype.compare can now compare sub-ranges of two Buffers
   (James M Snell) #5880

deps:
  * update to http-parser 2.7.0
    (Fedor Indutny) #6279
  * update ESLint to 2.7.0
    (silverwind) #6132

net:
  * adds support for passing DNS lookup hints to createConnection()
    (Colin Ihrig) #6000

node:
  * Make the builtin libraries available for the --eval and --print
    CLI options
    (Anna Henningsen) #6207

npm:
  * upgrade npm to 3.8.6
    (Kat Marchán) #6153

repl:
  * Pressing enter in the repl will repeat the last command by default
    if no input has been received. This behaviour was in node
    previously and was not removed intentionally.
    (Rich Trott) #6090

src:
  * add SIGINFO to supported signals
    (James Reggio) #6093

streams:
  * Fix a regression that caused by net streams requesting multiple
    chunks synchronously when combined with cork/uncork
    (Matteo Collina) #6164

zlib:
  * The flushing flag is now configurable allowing for decompression
    of partial data
    (Anna Henningsen) #6069

PR-URL: #6322
joelostrowski pushed a commit to joelostrowski/node that referenced this pull request Apr 25, 2016
Buffer:
  * Buffer.prototype.compare can now compare sub-ranges of two Buffers
   (James M Snell) nodejs#5880

deps:
  * update to http-parser 2.7.0
    (Fedor Indutny) nodejs#6279
  * update ESLint to 2.7.0
    (silverwind) nodejs#6132

net:
  * adds support for passing DNS lookup hints to createConnection()
    (Colin Ihrig) nodejs#6000

node:
  * Make the builtin libraries available for the --eval and --print
    CLI options
    (Anna Henningsen) nodejs#6207

npm:
  * upgrade npm to 3.8.6
    (Kat Marchán) nodejs#6153

repl:
  * Pressing enter in the repl will repeat the last command by default
    if no input has been received. This behaviour was in node
    previously and was not removed intentionally.
    (Rich Trott) nodejs#6090

src:
  * add SIGINFO to supported signals
    (James Reggio) nodejs#6093

streams:
  * Fix a regression that caused by net streams requesting multiple
    chunks synchronously when combined with cork/uncork
    (Matteo Collina) nodejs#6164

zlib:
  * The flushing flag is now configurable allowing for decompression
    of partial data
    (Anna Henningsen) nodejs#6069

PR-URL: nodejs#6322
jasnell pushed a commit that referenced this pull request Apr 26, 2016
net streams can request multiple chunks to be written in a synchronous
fashion. If this is combined with cork/uncork, en error is currently
thrown because of a regression introduced in:
89aeab9
(#4354).

Fixes: #6154
PR-URL: #6164
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
Reviewed-By: Mathias Buus <mathiasbuus@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
jasnell pushed a commit that referenced this pull request Apr 26, 2016
Buffer:
  * Buffer.prototype.compare can now compare sub-ranges of two Buffers
   (James M Snell) #5880

deps:
  * update to http-parser 2.7.0
    (Fedor Indutny) #6279
  * update ESLint to 2.7.0
    (silverwind) #6132

net:
  * adds support for passing DNS lookup hints to createConnection()
    (Colin Ihrig) #6000

node:
  * Make the builtin libraries available for the --eval and --print
    CLI options
    (Anna Henningsen) #6207

npm:
  * upgrade npm to 3.8.6
    (Kat Marchán) #6153

repl:
  * Pressing enter in the repl will repeat the last command by default
    if no input has been received. This behaviour was in node
    previously and was not removed intentionally.
    (Rich Trott) #6090

src:
  * add SIGINFO to supported signals
    (James Reggio) #6093

streams:
  * Fix a regression that caused by net streams requesting multiple
    chunks synchronously when combined with cork/uncork
    (Matteo Collina) #6164

zlib:
  * The flushing flag is now configurable allowing for decompression
    of partial data
    (Anna Henningsen) #6069

PR-URL: #6322
MylesBorins pushed a commit that referenced this pull request Apr 30, 2016
net streams can request multiple chunks to be written in a synchronous
fashion. If this is combined with cork/uncork, en error is currently
thrown because of a regression introduced in:
89aeab9
(#4354).

Fixes: #6154
PR-URL: #6164
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
Reviewed-By: Mathias Buus <mathiasbuus@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
@MylesBorins MylesBorins mentioned this pull request May 4, 2016
@mcollina mcollina deleted the unlimited-corked-requests branch May 18, 2016 14:47
@mcollina mcollina mentioned this pull request Jan 17, 2018
2 tasks
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