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: calling end while ending will never invoke callback? #28667

Closed
ronag opened this issue Jul 13, 2019 · 11 comments
Closed

streams: calling end while ending will never invoke callback? #28667

ronag opened this issue Jul 13, 2019 · 11 comments
Labels
stream Issues and PRs related to the stream subsystem.

Comments

@ronag
Copy link
Member

ronag commented Jul 13, 2019

Calling end() twice with callback will cause the second callback to never be invoked:

e.g. the following will fail.

writable.end(common.mustCall());
writable.end(common.mustCall());

I'm not sure what the behavior should be here. Maybe calling the callback with an error? Either way, not calling the callback at all seems to me like it will cause problems and memory leaks.

@ronag
Copy link
Member Author

ronag commented Jul 13, 2019

@mcollina ping

@ronag
Copy link
Member Author

ronag commented Jul 13, 2019

http/1 has the same "problem"

@lpinca
Copy link
Member

lpinca commented Jul 13, 2019

The callback is added as a listener of the 'finish' event so the behavior seems correct to me. The event is emitted only once.

@lpinca
Copy link
Member

lpinca commented Jul 13, 2019

There is no memory leak because the callback is used only on the first .end() call.

@lpinca lpinca added the stream Issues and PRs related to the stream subsystem. label Jul 13, 2019
@mcollina
Copy link
Member

I think adding an error to the callback if the stream has already emitted end could be accepted. We need to verify this would not break CITGM.

There should be enough state on Readable around to easily add a check.

@lpinca
Copy link
Member

lpinca commented Jul 14, 2019

I think adding an error to the callback if the stream has already emitted end could be accepted

You mean 'finish'? And what would you do with all callbacks between the first writable.end() and the actual 'finish' event? For example.

writable.on('finish', () => {
  writable.end(() => {
    // Called with an error.
  });
});

writable.end(() => {
  // Called when `'finish'` is emitted.
});

writable.end(() => {
  // Called when `'finish'` is emitted?
});

writable.end(() => {
  // Called when `'finish'` is emitted?
});

// ...

@ronag
Copy link
Member Author

ronag commented Jul 14, 2019

https://github.com/nodejs/node/blob/master/lib/_stream_writable.js#L592

if ending the callback is never registered anywhere?

@lpinca
Copy link
Member

lpinca commented Jul 14, 2019

Yes.

@ronag
Copy link
Member Author

ronag commented Jul 14, 2019

maybe?

writable.on('finish', () => {
  writable.end((err) => {
  	// error
  });
});

writable.end((err) => {
 // ok
});

writable.end((err) => {
  // error
});

writable.end((err) => {
  // error
});

I'm unsure...

@addaleax
Copy link
Member

@ronag I think that suggestion is just fine 👍 The only real alternative I could see is also calling the callbacks for the subsequent .end() calls, but one really should only have one .end() call…

Trott pushed a commit that referenced this issue Aug 20, 2019
Invoke callback with ERR_STREAM_ALREADY_FINISHED error if `end()` is
called on a finished stream.

PR-URL: #28687
Refs: #28667
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Trivikram Kamat <trivikr.dev@gmail.com>
Reviewed-By: Rich Trott <rtrott@gmail.com>
@ronag
Copy link
Member Author

ronag commented Aug 24, 2019

This has been sorted

@ronag ronag closed this as completed Aug 24, 2019
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

No branches or pull requests

4 participants