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

Always call callbacks in outgoing streams #2240

Closed
wants to merge 1 commit into from

Conversation

laino
Copy link

@laino laino commented Jul 24, 2015

Fixes: #1047

This is basically the same PR as #1143, but it includes some proposed changes.

@laino laino changed the title Fix https://github.com/nodejs/io.js/issues/1047 Always call callbacks in outgoing streams Jul 24, 2015
@Fishrock123 Fishrock123 added the http Issues or PRs related to the http subsystem. label Jul 24, 2015
@mikeal
Copy link
Contributor

mikeal commented Jul 24, 2015

Why isn't this handled by the base stream implementation?

@laino
Copy link
Author

laino commented Jul 24, 2015

@mikeal As far as I understand http outgoing streams have their own internal buffer. Data/Callbacks in that buffer haven't been written to the underlying "base" stream yet, so they won't be called with an error should the underlying stream close prematurely (i.e before the data was written).

This PR fixes that.

@mikeal
Copy link
Contributor

mikeal commented Jul 24, 2015

Yup, let me clarify a bit. I'm not commenting about the PR in a +1/-1 context, this is a bug and should be fixed and someone with more familiarity with the "gotchas" of new style streams should review it (in other words: not me).

I'm posing more of a question and possibly some longer term work (outside this PR) that should not interfere with this PR getting merged. I'm wondering why we can't inherit this functionality from the base stream implementation?

One of the major reasons for the streams rewrite was to provide a base we could actually use across all of stdlib. At the time of the rewrite many of the streams in core didn't inherit from core streams either for legacy reasons or because they needed to do something "special." Streams 2/3 dramatically complicated the internal stream API and issues like this will run rampant if everyone can't use the base classes effectively. To be reminded that we still have internal streams that are implementing one-off behavior not covered by the base streams and that we are still finding issues like this is troubling.

Perhaps we should add an Issue in the readable-stream repo for the Streams WG to try and provide an API in base streams that can handle the use case http is working around here by implementing its own buffer. If that sounds good I'll log that issue immediately so that we can stop polluting this PR with that discussion.

/cc @nodejs/streams


var callbackCalled = false;

res.end('ok', function() {
Copy link
Contributor

Choose a reason for hiding this comment

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

You can simply use res.end('ok', common.mustCall(function() {})). It will fail if the function is not called exactly once.

@trevnorris
Copy link
Contributor

Quick review looks clean. Let's run CI and see how it does. Also, might need to be rebased.

@laino
Copy link
Author

laino commented Sep 2, 2015

Rebased the PR and added changes proposed by @thefourtheye

@trevnorris
Copy link
Contributor

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

@laino The commit message will have to be updated to include subsystem, title and then a message body describing what's being fixed.

@joaocgreis
Copy link
Member

CI hit a problem with a RPi, it's waiting for solution but marked offline for now.

Started again: https://ci.nodejs.org/job/node-test-pull-request/238/

var err = new Error('write after end');
process.nextTick(function() {
self.emit('error', err);
if (callback) callback(err);
Copy link
Contributor

Choose a reason for hiding this comment

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

I feel like this is a strange hybrid between err-back and event emitter.

/cc @nodejs/tsc Feedback on basically emitting the error twice?

Copy link
Contributor

Choose a reason for hiding this comment

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

One or the other seems better. Maybe if (typeof callback === 'function') callback(err); else self.emit('error', err);

Copy link
Contributor

Choose a reason for hiding this comment

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

I think this had been discussed some time back. See nodejs/node-v0.x-archive#7477 where this change originated from.

IMHO it should only be one or the other, like @cjihrig says. If a callback is supplied, then pass the error and not emit. Otherwise emit.

Copy link
Member

Choose a reason for hiding this comment

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

+1. Down with double errors!!

Copy link
Contributor

Choose a reason for hiding this comment

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

I like that solution. @laino mind making that change?

@joaocgreis
Copy link
Member

Two tests failed in CI:

@trevnorris
Copy link
Contributor

@joaocgreis The CI system has been giving me sporadic errors all over the place today. I doubt it's related.

@orangemocha
Copy link
Contributor

One more test run: https://ci.nodejs.org/job/node-test-pull-request/239/

... to double check test-net-listen-shared-ports

@trevnorris
Copy link
Contributor

Awesome. All green.

@laino If you can make the change in emitting the error I think this will be ready to land.

// We *might* get a socket already closed error here, which
// occurs when the socket was destroyed before we finished
// writing our data.
res.on('error', function() {});
Copy link
Contributor

Choose a reason for hiding this comment

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

Then lets check the error here, just to be sure.

Copy link
Contributor

Choose a reason for hiding this comment

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

But should that error cause the test to fail? I don't believe this particular fail means what the test was created to test has failed.

Copy link
Contributor

Choose a reason for hiding this comment

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

As it is we simply ignore everything right? As the comment says, if we check if the error is actually socket closed error, wouldn't it be better?

Copy link
Contributor

Choose a reason for hiding this comment

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

oh I see what you're saying. good point. yes, checking for expected errors, but still throwing on unexpected errors, would be a smart thing to do.

@jasnell
Copy link
Member

jasnell commented Nov 16, 2015

@laino ... ping... there were a few additional comments here that needed to be addressed; and this PR would need to be rebased and updated before it could land. Thank you!

@benjamingr
Copy link
Member

Ping @laino

@jasnell jasnell added the stalled Issues and PRs that are stalled. label Apr 9, 2016
@jasnell
Copy link
Member

jasnell commented Jun 7, 2016

Closing given the lack of any further activity. The original issue is still open. Can reopen this if someone wishes to take it over but it would really need a new PR at this point.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
http Issues or PRs related to the http subsystem. stalled Issues and PRs that are stalled.
Projects
None yet
Development

Successfully merging this pull request may close these issues.