Skip to content

Commit bbf9f88

Browse files
committed
http: start connections checking interval on listen
1 parent 32eb492 commit bbf9f88

File tree

4 files changed

+69
-6
lines changed

4 files changed

+69
-6
lines changed

lib/_http_server.js

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -497,14 +497,14 @@ function storeHTTPOptions(options) {
497497
}
498498
}
499499

500-
function setupConnectionsTracking(server) {
500+
function setupConnectionsTracking() {
501501
// Start connection handling
502-
server[kConnections] = new ConnectionsList();
502+
this[kConnections] = new ConnectionsList();
503503

504504
// This checker is started without checking whether any headersTimeout or requestTimeout is non zero
505505
// otherwise it would not be started if such timeouts are modified after createServer.
506-
server[kConnectionsCheckingInterval] =
507-
setInterval(checkConnections.bind(server), server.connectionsCheckingInterval).unref();
506+
this[kConnectionsCheckingInterval] =
507+
setInterval(checkConnections.bind(this), this.connectionsCheckingInterval).unref();
508508
}
509509

510510
function httpServerPreClose(server) {
@@ -542,11 +542,12 @@ function Server(options, requestListener) {
542542
this.httpAllowHalfOpen = false;
543543

544544
this.on('connection', connectionListener);
545+
this.on('listening', setupConnectionsTracking);
545546

546547
this.timeout = 0;
547548
this.maxHeadersCount = null;
548549
this.maxRequestsPerSocket = 0;
549-
setupConnectionsTracking(this);
550+
550551
this[kUniqueHeaders] = parseUniqueHeadersOption(options.uniqueHeaders);
551552
}
552553
ObjectSetPrototypeOf(Server.prototype, net.Server.prototype);
@@ -558,6 +559,10 @@ Server.prototype.close = function() {
558559
};
559560

560561
Server.prototype.closeAllConnections = function() {
562+
if (!this[kConnections]) {
563+
return;
564+
}
565+
561566
const connections = this[kConnections].all();
562567

563568
for (let i = 0, l = connections.length; i < l; i++) {
@@ -566,6 +571,10 @@ Server.prototype.closeAllConnections = function() {
566571
};
567572

568573
Server.prototype.closeIdleConnections = function() {
574+
if (!this[kConnections]) {
575+
return;
576+
}
577+
569578
const connections = this[kConnections].idle();
570579

571580
for (let i = 0, l = connections.length; i < l; i++) {

lib/https.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,8 +94,9 @@ function Server(opts, requestListener) {
9494

9595
this.timeout = 0;
9696
this.maxHeadersCount = null;
97-
setupConnectionsTracking(this);
97+
this.on('listening', setupConnectionsTracking);
9898
}
99+
99100
ObjectSetPrototypeOf(Server.prototype, tls.Server.prototype);
100101
ObjectSetPrototypeOf(Server, tls.Server);
101102

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
'use strict';
2+
3+
// Flags: --expose-gc
4+
5+
// Check that creating a server without listening does not leak resources.
6+
7+
const common = require('../common');
8+
const onGC = require('../common/ongc');
9+
const Countdown = require('../common/countdown');
10+
11+
const http = require('http');
12+
const max = 100;
13+
14+
// Note that Countdown internally calls common.mustCall, that's why it's not done here.
15+
const countdown = new Countdown(max, () => {});
16+
17+
for (let i = 0; i < max; i++) {
18+
const server = http.createServer((req, res) => {});
19+
onGC(server, { ongc: countdown.dec.bind(countdown) });
20+
}
21+
22+
setTimeout(() => {
23+
global.gc();
24+
}, common.platformTimeout(500));
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
'use strict';
2+
3+
// Flags: --expose-gc
4+
5+
// Check that creating a server without listening does not leak resources.
6+
7+
const common = require('../common');
8+
9+
if (!common.hasCrypto) {
10+
common.skip('missing crypto');
11+
}
12+
13+
const onGC = require('../common/ongc');
14+
const Countdown = require('../common/countdown');
15+
16+
const https = require('https');
17+
const max = 100;
18+
19+
// Note that Countdown internally calls common.mustCall, that's why it's not done here.
20+
const countdown = new Countdown(max, () => {});
21+
22+
for (let i = 0; i < max; i++) {
23+
const server = https.createServer((req, res) => {});
24+
onGC(server, { ongc: countdown.dec.bind(countdown) });
25+
}
26+
27+
setTimeout(() => {
28+
global.gc();
29+
}, common.platformTimeout(500));

0 commit comments

Comments
 (0)