http: prevent aborted event when request is complete#18999
http: prevent aborted event when request is complete#18999billywhizz wants to merge 4 commits intonodejs:masterfrom
Conversation
When socket is closed on a response for a request that is being piped to a stream there is a condition where aborted event will be fired to http client when socket is closing and the incomingMessage stream is still set to readable. We need a check for request being complete and to only raise the 'aborted' event on the http client if we have not yet completed reading the response from the server. Fixes: nodejs#18756
Tests in progress to reproduce issue consistently. Fixes: nodejs#18756
| headers['Content-Length'] = 50; | ||
| const socket = res.socket; | ||
| res.writeHead(200, headers); | ||
| setTimeout(() => res.write('aaaaaaaaaa'), 100); |
There was a problem hiding this comment.
Shouldn't all of these timers be setTimeout(..., common.platformTimeout(n)) instead? Otherwise, is there a more reliable way to trigger this issue (perhaps using nextTick() and/or setImmediate() or something else)?
mcollina
left a comment
There was a problem hiding this comment.
Good work! The change itself is fine, I've left some notes on the test.
| res.pipe(fstream); | ||
| const _handle = res.socket._handle; | ||
| _handle._close = res.socket._handle.close; | ||
| _handle.close = function(callback) { |
There was a problem hiding this comment.
Can you explain why are you overriding this here?
There was a problem hiding this comment.
because i could not find a way of forcing the condition we get intermittently in the wild. if you run this script and leave it it will eventually start aborting requests that are actually complete: https://gist.github.com/billywhizz/b500a0d4708f89625ddbb313601b5363. i was unable to figure out how to recreate those exact conditions in a test but after debugging i could see the aborted event was being fired even though req.res.complete was = true. so i overrode close here to recreate that condition.
There was a problem hiding this comment.
to clarify, the error occurs when req.res.complete = true and res.readable is still = true. that is happening in the wild but don't know how to force it for a test. i imagine it will depend on a specific sequence of TCP session interactions.
| const finishCountdown = new Countdown(N, common.mustCall(() => { | ||
| server.close(); | ||
| })); | ||
| const reqCountdown = new Countdown(N, common.mustCall()); |
There was a problem hiding this comment.
I would prefer if N was not a constant, but rather it uses a two steps approach, maybe with some helpers.
It's not clear why you are calling twice too.
There was a problem hiding this comment.
it's running two tests - one to ensure we don't abort a good request, one to ensure we do abort a bad one. i can refactor to take out the countdown timers altogether. was trying to stay close to how other tests are constructed. if you can suggest how to change i am happy to refactor.
| assert.strictEqual(res.statusCode, 200); | ||
| assert.strictEqual(res.headers.connection, 'close'); | ||
| let aborted = false; | ||
| const fstream = fs.createWriteStream(fname); |
There was a problem hiding this comment.
I think this file can be made more simple.
No need to cleanup and fs module.
const { Writable } = require('stream');
// ...
const writable = new Writable({
write(chunk, encoding, callback) {
callback();
}
});
res.pipe(writable);
// ...
writable.on('finish', () => {|
CI: https://ci.nodejs.org/job/node-test-pull-request/13394/ Let's see what CI and CITGM think. |
|
let me know if there is anything else i need to do guys. thx |
|
Landed in 3828fc6...38eb0fa |
When socket is closed on a response for a request that is being piped to a stream there is a condition where aborted event will be fired to http client when socket is closing and the incomingMessage stream is still set to readable. We need a check for request being complete and to only raise the 'aborted' event on the http client if we have not yet completed reading the response from the server. Fixes: #18756 PR-URL: #18999 Reviewed-By: Shingo Inoue <leko.noor@gmail.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com>
PR-URL: #18999 Reviewed-By: Shingo Inoue <leko.noor@gmail.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com>
|
@Leko please squash commits next time before landing. |
|
@lpinca I got it. I'm sorry for mistaken. |
|
No problem. |
When socket is closed on a response for a request that is being piped to a stream there is a condition where aborted event will be fired to http client when socket is closing and the incomingMessage stream is still set to readable. We need a check for request being complete and to only raise the 'aborted' event on the http client if we have not yet completed reading the response from the server. Fixes: nodejs#18756 PR-URL: nodejs#18999 Reviewed-By: Shingo Inoue <leko.noor@gmail.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com>
Tests in progress to reproduce issue consistently. Fixes: nodejs#18756 PR-URL: nodejs#18999 Reviewed-By: Shingo Inoue <leko.noor@gmail.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com>
PR-URL: nodejs#18999 Reviewed-By: Shingo Inoue <leko.noor@gmail.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com>
When socket is closed on a response for a request that is being piped to a stream there is a condition where aborted event will be fired to http client when socket is closing and the incomingMessage stream is still set to readable. We need a check for request being complete and to only raise the 'aborted' event on the http client if we have not yet completed reading the response from the server. Fixes: nodejs#18756 PR-URL: nodejs#18999 Reviewed-By: Shingo Inoue <leko.noor@gmail.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com>
Tests in progress to reproduce issue consistently. Fixes: nodejs#18756 PR-URL: nodejs#18999 Reviewed-By: Shingo Inoue <leko.noor@gmail.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com>
PR-URL: nodejs#18999 Reviewed-By: Shingo Inoue <leko.noor@gmail.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com>
When socket is closed on a response for a request that is being piped to a stream there is a condition where aborted event will be fired to http client when socket is closing and the incomingMessage stream is still set to readable. We need a check for request being complete and to only raise the 'aborted' event on the http client if we have not yet completed reading the response from the server. Fixes: nodejs#18756 PR-URL: nodejs#18999 Reviewed-By: Shingo Inoue <leko.noor@gmail.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com>
Tests in progress to reproduce issue consistently. Fixes: nodejs#18756 PR-URL: nodejs#18999 Reviewed-By: Shingo Inoue <leko.noor@gmail.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com>
PR-URL: nodejs#18999 Reviewed-By: Shingo Inoue <leko.noor@gmail.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com>
When socket is closed on a response for a request that is being piped to a stream there is a condition where aborted event will be fired to http client when socket is closing and the incomingMessage stream is still set to readable. We need a check for request being complete and to only raise the 'aborted' event on the http client if we have not yet completed reading the response from the server. Fixes: #18756 Backport-PR-URL: #22380 PR-URL: #18999 Reviewed-By: Shingo Inoue <leko.noor@gmail.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com>
make -j4 test(UNIX), orvcbuild test(Windows) passesAffected core subsystem(s)
http
When socket is closed on a response for a request that is being piped to a stream
there is a condition where aborted event will be fired to http client when socket is
closing and the incomingMessage stream is still set to readable.
We need a check for request being complete and to only raise the 'aborted' event
on the http client if we have not yet completed reading the response from the server.