Skip to content

Commit e0a9ad1

Browse files
lpincajasnell
authored andcommitted
http: avoid retaining unneeded memory
Prevent the events listeners of the sockets obtained with the HTTP upgrade mechanism from retaining unneeded memory. Ref: #11868 PR-URL: #11926 Reviewed-By: James M Snell <[email protected]> Reviewed-By: Colin Ihrig <[email protected]> Reviewed-By: Ben Noordhuis <[email protected]>
1 parent 4eb194a commit e0a9ad1

File tree

3 files changed

+29
-27
lines changed

3 files changed

+29
-27
lines changed

lib/_http_common.js

+1-5
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ const methods = binding.methods;
2626
const HTTPParser = binding.HTTPParser;
2727

2828
const FreeList = require('internal/freelist').FreeList;
29+
const ondrain = require('internal/http').ondrain;
2930
const incoming = require('_http_incoming');
3031
const IncomingMessage = incoming.IncomingMessage;
3132
const readStart = incoming.readStart;
@@ -222,11 +223,6 @@ function freeParser(parser, req, socket) {
222223
}
223224

224225

225-
function ondrain() {
226-
if (this._httpMessage) this._httpMessage.emit('drain');
227-
}
228-
229-
230226
function httpSocketSetup(socket) {
231227
socket.removeListener('drain', ondrain);
232228
socket.on('drain', ondrain);

lib/_http_server.js

+22-21
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ const continueExpression = common.continueExpression;
3434
const chunkExpression = common.chunkExpression;
3535
const httpSocketSetup = common.httpSocketSetup;
3636
const OutgoingMessage = require('_http_outgoing').OutgoingMessage;
37-
const outHeadersKey = require('internal/http').outHeadersKey;
37+
const { outHeadersKey, ondrain } = require('internal/http');
3838

3939
const STATUS_CODES = {
4040
100: 'Continue',
@@ -296,7 +296,7 @@ function connectionListener(socket) {
296296
// otherwise, destroy on timeout by default
297297
if (this.timeout)
298298
socket.setTimeout(this.timeout);
299-
socket.on('timeout', socketOnTimeout.bind(undefined, this, socket));
299+
socket.on('timeout', socketOnTimeout);
300300

301301
var parser = parsers.alloc();
302302
parser.reinitialize(HTTPParser.REQUEST);
@@ -314,9 +314,9 @@ function connectionListener(socket) {
314314

315315
var state = {
316316
onData: null,
317-
onError: null,
318317
onEnd: null,
319318
onClose: null,
319+
onDrain: null,
320320
outgoing: [],
321321
incoming: [],
322322
// `outgoingData` is an approximate amount of bytes queued through all
@@ -326,21 +326,20 @@ function connectionListener(socket) {
326326
outgoingData: 0
327327
};
328328
state.onData = socketOnData.bind(undefined, this, socket, parser, state);
329-
state.onError = socketOnError.bind(undefined, this, socket, state);
330329
state.onEnd = socketOnEnd.bind(undefined, this, socket, parser, state);
331330
state.onClose = socketOnClose.bind(undefined, socket, state);
331+
state.onDrain = socketOnDrain.bind(undefined, socket, state);
332332
socket.on('data', state.onData);
333-
socket.on('error', state.onError);
333+
socket.on('error', socketOnError);
334334
socket.on('end', state.onEnd);
335335
socket.on('close', state.onClose);
336+
socket.on('drain', state.onDrain);
336337
parser.onIncoming = parserOnIncoming.bind(undefined, this, socket, state);
337338

338339
// We are consuming socket, so it won't get any actual data
339340
socket.on('resume', onSocketResume);
340341
socket.on('pause', onSocketPause);
341342

342-
socket.on('drain', socketOnDrain.bind(undefined, socket, state));
343-
344343
// Override on to unconsume on `data`, `readable` listeners
345344
socket.on = socketOnWrap;
346345

@@ -378,15 +377,15 @@ function socketOnDrain(socket, state) {
378377
}
379378
}
380379

381-
function socketOnTimeout(server, socket) {
382-
var req = socket.parser && socket.parser.incoming;
383-
var reqTimeout = req && !req.complete && req.emit('timeout', socket);
384-
var res = socket._httpMessage;
385-
var resTimeout = res && res.emit('timeout', socket);
386-
var serverTimeout = server.emit('timeout', socket);
380+
function socketOnTimeout() {
381+
var req = this.parser && this.parser.incoming;
382+
var reqTimeout = req && !req.complete && req.emit('timeout', this);
383+
var res = this._httpMessage;
384+
var resTimeout = res && res.emit('timeout', this);
385+
var serverTimeout = this.server.emit('timeout', this);
387386

388387
if (!reqTimeout && !resTimeout && !serverTimeout)
389-
socket.destroy();
388+
this.destroy();
390389
}
391390

392391
function socketOnClose(socket, state) {
@@ -413,7 +412,7 @@ function socketOnEnd(server, socket, parser, state) {
413412

414413
if (ret instanceof Error) {
415414
debug('parse error');
416-
state.onError(ret);
415+
socketOnError.call(socket, ret);
417416
return;
418417
}
419418

@@ -443,19 +442,19 @@ function onParserExecute(server, socket, parser, state, ret, d) {
443442
onParserExecuteCommon(server, socket, parser, state, ret, undefined);
444443
}
445444

446-
function socketOnError(server, socket, state, e) {
445+
function socketOnError(e) {
447446
// Ignore further errors
448-
socket.removeListener('error', state.onError);
449-
socket.on('error', () => {});
447+
this.removeListener('error', socketOnError);
448+
this.on('error', () => {});
450449

451-
if (!server.emit('clientError', e, socket))
452-
socket.destroy(e);
450+
if (!this.server.emit('clientError', e, this))
451+
this.destroy(e);
453452
}
454453

455454
function onParserExecuteCommon(server, socket, parser, state, ret, d) {
456455
if (ret instanceof Error) {
457456
debug('parse error');
458-
state.onError(ret);
457+
socketOnError.call(socket, ret);
459458
} else if (parser.incoming && parser.incoming.upgrade) {
460459
// Upgrade or CONNECT
461460
var bytesParsed = ret;
@@ -468,6 +467,8 @@ function onParserExecuteCommon(server, socket, parser, state, ret, d) {
468467
socket.removeListener('data', state.onData);
469468
socket.removeListener('end', state.onEnd);
470469
socket.removeListener('close', state.onClose);
470+
socket.removeListener('drain', state.onDrain);
471+
socket.removeListener('drain', ondrain);
471472
unconsume(parser, socket);
472473
parser.finish();
473474
freeParser(parser, req, null);

lib/internal/http.js

+6-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
'use strict';
22

3+
function ondrain() {
4+
if (this._httpMessage) this._httpMessage.emit('drain');
5+
}
6+
37
module.exports = {
4-
outHeadersKey: Symbol('outHeadersKey')
8+
outHeadersKey: Symbol('outHeadersKey'),
9+
ondrain,
510
};

0 commit comments

Comments
 (0)