http: fix event listener leak

Fixes: https://github.com/nodejs/node/issues/29239
PR-URL: https://github.com/nodejs/node/pull/29245
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Reviewed-By: Jiawen Geng <technicalcute@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
This commit is contained in:
Robert Nagy 2019-08-21 15:12:48 +02:00 committed by Rich Trott
parent 4e188b3c63
commit f39ad8a91f
2 changed files with 12 additions and 1 deletions

View File

@ -506,6 +506,7 @@ function socketOnData(d) {
!statusIsInformational(parser.incoming.statusCode)) { !statusIsInformational(parser.incoming.statusCode)) {
socket.removeListener('data', socketOnData); socket.removeListener('data', socketOnData);
socket.removeListener('end', socketOnEnd); socket.removeListener('end', socketOnEnd);
socket.removeListener('drain', ondrain);
freeParser(parser, req, socket); freeParser(parser, req, socket);
} }
} }
@ -613,6 +614,7 @@ function responseKeepAlive(res, req) {
} }
socket.removeListener('close', socketCloseListener); socket.removeListener('close', socketCloseListener);
socket.removeListener('error', socketErrorListener); socket.removeListener('error', socketErrorListener);
socket.removeListener('drain', ondrain);
socket.once('error', freeSocketErrorListener); socket.once('error', freeSocketErrorListener);
// There are cases where _handle === null. Avoid those. Passing null to // There are cases where _handle === null. Avoid those. Passing null to
// nextTick() will call getDefaultTriggerAsyncId() to retrieve the id. // nextTick() will call getDefaultTriggerAsyncId() to retrieve the id.

View File

@ -52,7 +52,7 @@ function get(path, callback) {
port: server.address().port, port: server.address().port,
agent: agent, agent: agent,
path: path path: path
}, callback); }, callback).on('socket', common.mustCall(checkListeners));
} }
function checkDataAndSockets(body) { function checkDataAndSockets(body) {
@ -134,3 +134,12 @@ server.listen(0, common.mustCall(() => {
})); }));
})); }));
})); }));
// Check for listener leaks when reusing sockets.
function checkListeners(socket) {
assert.strictEqual(socket.listenerCount('data'), 1);
assert.strictEqual(socket.listenerCount('drain'), 1);
assert.strictEqual(socket.listenerCount('error'), 1);
// Sockets have onReadableStreamEnd.
assert.strictEqual(socket.listenerCount('end'), 2);
}