http: emit ERR_STREAM_DESTROYED if the socket is destroyed #29227
Conversation
| }); | ||
|
|
||
| req.on('response', common.mustNotCall()); | ||
| req.on('error', common.mustCall()); |
BridgeAR
Aug 20, 2019
Member
If I am not mistaken, this results in the ERR_STREAM_DESTROYED as well?
| req.on('error', common.mustCall()); | |
| req.on('error', common.expectsError({ | |
| code: 'ERR_STREAM_DESTROYED' | |
| })); |
Trott
Aug 23, 2019
Member
ping @mcollina Does that suggestion above seem good to you? (Seems good to me....)
| callback(err); | ||
| } | ||
| if (this.listenerCount('error') > 0 && this[kErrored] === undefined) { | ||
| this[kErrored] = true; |
BridgeAR
Aug 20, 2019
Member
Is there a specific reason to silence all errors besides the first one?
mcollina
Aug 20, 2019
Author
Member
The reason is that this will normally be called 4 times in case this condition is met, as a response is composed of 4 chunks.
|
Should probably also apply the |
| if (callback) { | ||
| callback(err); | ||
| } | ||
| if (this.listenerCount('error') > 0 && this[kErrored] === undefined) { |
ronag
Aug 20, 2019
Member
What's the reason for the listener count check? We don't do this for streams?
mcollina
Aug 20, 2019
Author
Member
The reason is not to break a lot of tests, and keep this semver-minor.
ronag
Aug 20, 2019
Member
Could you add a comment for that at least? Then maybe we can "fix" it in a semver-major in the future?
| @@ -56,6 +57,7 @@ const HIGH_WATER_MARK = getDefaultHighWaterMark(); | |||
| const { CRLF, debug } = common; | |||
|
|
|||
| const kIsCorked = Symbol('isCorked'); | |||
| const kErrored = Symbol('errored'); | |||
ronag
Aug 20, 2019
•
Member
Should we initialize kErrored in the constructor? Or will that unnecessarily increase object size?
mcollina
Aug 20, 2019
Author
Member
I'm not adding that to the constructor exactly because of that. I can add it if we think it's worth adding, it's not a big deal anyway.
| } | ||
| if (this.listenerCount('error') > 0 && this[kErrored] === undefined) { | ||
| this[kErrored] = true; | ||
| this.emit('error', err); |
ronag
Aug 20, 2019
•
Member
I believe this should be emitted in next tick? That's what we want in stream?
mcollina
Aug 20, 2019
Author
Member
I'm actually removing calling the callback here. It's not needed to fix the actual issue, and it can be done in a later step.
mcollina
Aug 20, 2019
Author
Member
We cannot remove the callback or something else is going to fail. Essentially if we want to emit error here, we need to call the callback synchronously first :/.
ronag
Aug 20, 2019
•
Member
Something else, as in a test? Add another comment for future semver-major?
I'm not sure about that. The reason I added |
Could you explain a little further? In |
|
The overall reason for not doing that in this PR is to keep it as strictly semver-minor as possible, so it can be backported. |
Sounds reasonable. I'm willing to make a semver-major PR in the future to make it more stream-like. |
|
Rebased and force-pushed to get rid of conflict. |
|
CI is not flaky, windows is failing :/
|
8ae28ff
to
2935f72
|
@ronag if you would like to take this over please do. |
|
This issue/PR was marked as stalled, it will be automatically closed in 30 days. If it should remain open, please leave a comment explaining why it should remain open. |
|
@ronag wdyt? Should we revive this or should I close it? |
|
@mcollina: I think this PR is no longer making correct assumptions. Streams do not emit If the underlying socket is prematurely destroyed (without error) that should already error the What we should probably fix is:
I would recommend we close this PR and make an issue for the callback and pipeline issue. Thoughts? |
|
I'll close this. Could you open the issue? |
The pipeline utility assumes that a stream is going to error if it
could not be written to it. If an http.OutgoingMessage was piped after
the underlining socket had been destroyed, the whole pipeline would not
be teared down, resulting in a file descriptor and memory leak.
Checklist
make -j4 test(UNIX), orvcbuild test(Windows) passes