GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — stream: invoke buffered write callbacks on error by ronag · Pull Request #30596 · nodejs/node

Conversation

@ronag

@ronag ronag commented Nov 22, 2019 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Member

Buffered write callbacks were only invoked upon error if autoDestroy is enabled.

Checklist
  • make -j4 test (UNIX), or vcbuild test (Windows) passes
  • tests and/or benchmarks are included
  • documentation is changed or added
  • commit message follows commit guidelines

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

bricss reacted with thumbs up emoji
All reactions
  • 👍 1 reaction
@nodejs-github-bot nodejs-github-bot added the stream Issues and PRs related to Node.js streams. label Nov 22, 2019
ronag
ronag commented Nov 22, 2019
View reviewed changes
Comment thread lib/_stream_writable.js Resolved

Uh oh!

There was an error while loading. Please reload this page.

@ronag

ronag commented Nov 22, 2019

Copy link
Copy Markdown
Member Author

Added comment and fixed linting

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

mcollina
mcollina approved these changes Nov 22, 2019
View reviewed changes

@mcollina mcollina left a comment

Copy link
Copy Markdown
Member

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

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
@mcollina mcollina added dont-land-on-v10.x labels Nov 22, 2019
@mcollina

mcollina commented Nov 22, 2019

Copy link
Copy Markdown
Member

@ronag Is this based on a semver-major commit that landed in 13? Are the above labels correct?

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@ronag

ronag commented Nov 22, 2019

Copy link
Copy Markdown
Member Author

@mcollina: Yes it is based on #29028 which landed in 13. Labels look correct.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@ronag

ronag commented Nov 22, 2019

Copy link
Copy Markdown
Member Author

I'll try to advise on those labels in future PR's.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@lpinca

lpinca commented Nov 22, 2019

Copy link
Copy Markdown
Member

Are you sure this is a good idea? Technically those writes never happened so why their callbacks are invoked? I noticed that this behavior was introduced in #29028. I missed it.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@ronag

ronag commented Nov 22, 2019 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Member Author

@lpinca: Not invoking callbacks in a callback based API is in my opinon very strange and could lead to deadlocks.

e.g. this could deadlock...

async function writePacket () {
  dst.write('header')
  for (const data of src) {
    await new Promise((resolve, reject) => 
      dst.write(data, err => err ? reject(err) : resolve()
    )
  }
}

Not saying that's the best way to do that, but it should still be valid.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@lpinca

lpinca commented Nov 22, 2019 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Member

Invoking all of them synchronously with an error that say "Cannot call write after a stream was destroyed" is not much better imho because:

  1. The stream was not destroyed when write was called
  2. It makes me think that buffered writes are attempted even after a stream is destroyed
All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@ronag

ronag commented Nov 22, 2019 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Member Author

Well in this case the error basically means and says that it wasn't attempted... no?

In a callback based API if the operation is not attempted you still call the callback with something like aborted.

If we promisified the API. Would the returned promise possibly never resolve nor reject in your opinion?

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@lpinca

lpinca commented Nov 22, 2019

Copy link
Copy Markdown
Member

In a callback based API if the operation is not attempted you still call the callback with something like aborted.

Hmm I don't buy it in this case because the actual failure is already signaled on the stream and all writes are bound to it, so it's obvious that if it is no longer writable no more writes will be done. No writes attempted no callbacks.

I preferred previous behavior but I guess it's too late :)

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@mcollina

mcollina commented Nov 22, 2019

Copy link
Copy Markdown
Member

If you call a function with a calback, the expectation throughout our codebase is that the callback is called.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

addaleax
addaleax approved these changes Nov 22, 2019
View reviewed changes
@lpinca

lpinca commented Nov 23, 2019 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Member

If you call a function with a calback, the expectation throughout our codebase is that the callback is called.

Is it? Here is one example where the callback is not called regardless of this change.

const { createDeflateRaw } = require('zlib');
const { randomBytes } = require('crypto');

const deflate = createDeflateRaw();

deflate.resume();
deflate.write(randomBytes(1024));
deflate.flush(function() {
  throw new Error('Unexpected callback invocation');
});

process.nextTick(function() {
  deflate.close();
});
All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@ronag

ronag commented Nov 23, 2019

Copy link
Copy Markdown
Member Author

Is it? Here is one example where the callback is not called regardless of this change.

We should probably fix that as well...

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@lpinca

lpinca commented Nov 23, 2019

Copy link
Copy Markdown
Member

We should probably fix that as well...

And many more, I guess.

ronag reacted with thumbs up emoji
All reactions
  • 👍 1 reaction

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

lpinca
lpinca reviewed Nov 23, 2019
View reviewed changes
Comment thread lib/_stream_writable.js Resolved

Uh oh!

There was an error while loading. Please reload this page.

@lpinca

lpinca commented Nov 23, 2019 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Member

Sorry to pester but there is one more thing which makes me very uncomfortable with this behavior.

const { Writable } = require('stream');

function callback1(err) {
  console.log('callback 1', err);
}

function callback2(err) {
  console.log('callback 2', err);
}

const chunk = Buffer.alloc(1024);

const writable = new Writable({
  write(chunk, encoding, callback) {
    setTimeout(callback, 1000);
  }
});

writable.on('close', function() {
  console.log('close');
});

writable.write(chunk, callback1);
writable.write(chunk, callback2);

setTimeout(function() {
  writable.destroy();
}, 500);

Callbacks of queued writes can be called before a callback (or possibly callbacks in case of _writev()) of a write in progress. That is callback order is no longer respected.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@ronag

ronag commented Nov 23, 2019

Copy link
Copy Markdown
Member Author

Sorry to pester but there is one more thing which makes me very uncomfortable with this behavior.

No worries.

Callbacks of queued writes can be called before a callback (or possibly callbacks in case of _writev()) of write in progress. That is callback order is no longer respected.

I'm not sure I follow? The write callback is called first and then any queued callbacks. Order is maintained? Do you think you can write a failing test I can look into?

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@ronag

ronag commented Nov 23, 2019 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Member Author

@lpinca: I think the behaviour you are referring to is what's done in #29028, not something this PR changes? If so I would propose we take that as a separate issue. I'm not sure whether destroy acts like you describe but I if so I think it can be changed so that be buffered callbacks are invoked after all active write calls are completed.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@lpinca

lpinca commented Nov 23, 2019

Copy link
Copy Markdown
Member

Yes correct, too bad I missed that PR. Anyway I think it is relevant here too because this patch extends that behavior to streams that do not use autoDestroy.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@ronag

ronag commented Nov 23, 2019 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Member Author

extends that behavior to streams that do not use autoDestroy.

Yes, but it happens in onwriteError when there is no active write.

@lpinca: If you create an issue and assign it to me I will try to resolve your concern in a follow up PR to this.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@ronag
ronag force-pushed the fix-write-callbacks branch from 1bef798 to 7dec5bb Compare November 23, 2019 13:53
@ronag

ronag commented Nov 23, 2019

Copy link
Copy Markdown
Member Author

The state.length change broke this PR. Investigating.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@ronag

ronag commented Nov 23, 2019 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Member Author

@lpinca Doesn't seem to much of a trouble to fix. I've included a fix commit for your concern in this PR. I'll move it to a separate PR if that's preferable.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@ronag
ronag requested a review from mcollina November 23, 2019 14:14
@BridgeAR BridgeAR added author ready PRs with CI started, the required approvals, and no outstanding review comments. and removed author ready PRs with CI started, the required approvals, and no outstanding review comments. labels Dec 24, 2019
@nodejs-github-bot

nodejs-github-bot commented Dec 25, 2019

Copy link
Copy Markdown
Collaborator

CI: https://ci.nodejs.org/job/node-test-pull-request/27930/

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@nodejs-github-bot

nodejs-github-bot commented Dec 25, 2019

Copy link
Copy Markdown
Collaborator

CI: https://ci.nodejs.org/job/node-test-pull-request/27942/

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@nodejs-github-bot

nodejs-github-bot commented Dec 25, 2019

Copy link
Copy Markdown
Collaborator

CI: https://ci.nodejs.org/job/node-test-pull-request/27948/

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

Trott pushed a commit that referenced this pull request Dec 31, 2019
@ronag @Trott
stream: invoke buffered write callbacks on error
e66c4de
Buffered write callbacks were only invoked upon
error if `autoDestroy` was invoked.

PR-URL: #30596
Reviewed-By: Matteo Collina <[email protected]>
Reviewed-By: Anna Henningsen <[email protected]>
Reviewed-By: Luigi Pinca <[email protected]>
Reviewed-By: Rich Trott <[email protected]>
@Trott

Trott commented Dec 31, 2019

Copy link
Copy Markdown
Member

Landed in e66c4de

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@Trott Trott closed this Dec 31, 2019
@BridgeAR

BridgeAR commented Jan 3, 2020

Copy link
Copy Markdown
Member

This does not land cleanly on v13.x. Please open a manual backport in case this should be backported or leave a comment to update the labels in case it should not be backported.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@BridgeAR BridgeAR added the backport-requested-v13.x label Jan 3, 2020
@ronag ronag mentioned this pull request Jan 3, 2020
[v13.x backport] stream: invoke buffered write callbacks on error #31179
Closed
4 tasks done
ronag added a commit to nxtedition/node that referenced this pull request Jan 3, 2020
@ronag
stream: invoke buffered write callbacks on error
03b85ec
Buffered write callbacks were only invoked upon
error if `autoDestroy` was invoked.

Backport-PR-URL: nodejs#31179
PR-URL: nodejs#30596
Reviewed-By: Matteo Collina <[email protected]>
Reviewed-By: Anna Henningsen <[email protected]>
Reviewed-By: Luigi Pinca <[email protected]>
Reviewed-By: Rich Trott <[email protected]>
@ronag

ronag commented Jan 3, 2020

Copy link
Copy Markdown
Member Author

Done, #31179

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@lpinca lpinca mentioned this pull request Jan 11, 2020
Recent behavior change of buffered write callbacks #31317
Closed
@ronag ronag added backport-open-v12.x and removed backport-open-v12.x labels Jan 28, 2020
@lpinca lpinca mentioned this pull request Feb 25, 2020
Node.js Technical Steering Committee (TSC) Meeting 2020-02-26 nodejs/TSC#827
Closed
codebytere pushed a commit that referenced this pull request Feb 29, 2020
@ronag @codebytere
stream: invoke buffered write callbacks on error
d0a0071
Refs: #30596

Buffered write callbacks were only invoked upon
error if `autoDestroy` was invoked.

Backport-PR-URL: #31179
PR-URL: #30596
Reviewed-By: Matteo Collina <[email protected]>
Reviewed-By: Anna Henningsen <[email protected]>
Reviewed-By: Luigi Pinca <[email protected]>
Reviewed-By: Rich Trott <[email protected]>
@codebytere codebytere added backported-to-v13.x and removed backport-open-v13.x labels Feb 29, 2020
@codebytere codebytere mentioned this pull request Feb 29, 2020
v13.10.0 proposal #32027
Merged
lpinca added a commit to websockets/ws that referenced this pull request Mar 3, 2020
@lpinca
[fix] Call buffered send callbacks on abnormal closure
f2c57e8
If the socket is closed while data is being compressed, invoke the
current send callback and the buffered send callbacks with an error
before emitting the `'close'` event.

Refs: nodejs/node#30596
@lpinca lpinca mentioned this pull request Mar 3, 2020
Call buffered send callbacks on abnormal closure websockets/ws#1702
Merged
lpinca added a commit to websockets/ws that referenced this pull request Mar 7, 2020
@lpinca
[fix] Call buffered send callbacks on abnormal closure (#1702)
b29154b
If the socket is closed while data is being compressed, invoke the
current send callback and the buffered send callbacks with an error
before emitting the `'close'` event.

Refs: nodejs/node#30596
This was referenced Sep 16, 2026
fix(daemon): pause producers when stream backlogs grow stablyai/orca#20947
Merged
node:net: emit 'error' once when a buffered write on an adopted fd fails oven-sh/bun#43038
Open
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Reviewers

@mcollina mcollina mcollina approved these changes
@Trott Trott Trott approved these changes
@addaleax addaleax addaleax approved these changes
@lpinca lpinca lpinca approved these changes

Uh oh!

There was an error while loading. Please reload this page.

Assignees

No one assigned

Labels

author ready PRs with CI started, the required approvals, and no outstanding review comments. stream Issues and PRs related to Node.js streams.

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

Uh oh!

There was an error while loading. Please reload this page.

8 participants

@ronag @mcollina @lpinca @addaleax @nodejs-github-bot @Trott @BridgeAR @codebytere
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
You are visitor 01402520 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.