Skip to content

Commit 8490318

Browse files
ShogunPandalpinca
andauthored
http: start connections checking interval on listen
Co-authored-by: Luigi Pinca <luigipinca@gmail.com> PR-URL: #48611 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Marco Ippolito <marcoippolito54@gmail.com> Reviewed-By: Luigi Pinca <luigipinca@gmail.com> Reviewed-By: Rafael Gonzaga <rafael.nunu@hotmail.com>
1 parent 5cbf73e commit 8490318

4 files changed

+71
-6
lines changed

lib/_http_server.js

+16-5
Original file line numberDiff line numberDiff line change
@@ -500,14 +500,16 @@ function storeHTTPOptions(options) {
500500
}
501501
}
502502

503-
function setupConnectionsTracking(server) {
503+
function setupConnectionsTracking() {
504504
// Start connection handling
505-
server[kConnections] = new ConnectionsList();
505+
if (!this[kConnections]) {
506+
this[kConnections] = new ConnectionsList();
507+
}
506508

507509
// This checker is started without checking whether any headersTimeout or requestTimeout is non zero
508510
// otherwise it would not be started if such timeouts are modified after createServer.
509-
server[kConnectionsCheckingInterval] =
510-
setInterval(checkConnections.bind(server), server.connectionsCheckingInterval).unref();
511+
this[kConnectionsCheckingInterval] =
512+
setInterval(checkConnections.bind(this), this.connectionsCheckingInterval).unref();
511513
}
512514

513515
function httpServerPreClose(server) {
@@ -545,11 +547,12 @@ function Server(options, requestListener) {
545547
this.httpAllowHalfOpen = false;
546548

547549
this.on('connection', connectionListener);
550+
this.on('listening', setupConnectionsTracking);
548551

549552
this.timeout = 0;
550553
this.maxHeadersCount = null;
551554
this.maxRequestsPerSocket = 0;
552-
setupConnectionsTracking(this);
555+
553556
this[kUniqueHeaders] = parseUniqueHeadersOption(options.uniqueHeaders);
554557
}
555558
ObjectSetPrototypeOf(Server.prototype, net.Server.prototype);
@@ -565,6 +568,10 @@ Server.prototype[SymbolAsyncDispose] = async function() {
565568
};
566569

567570
Server.prototype.closeAllConnections = function() {
571+
if (!this[kConnections]) {
572+
return;
573+
}
574+
568575
const connections = this[kConnections].all();
569576

570577
for (let i = 0, l = connections.length; i < l; i++) {
@@ -573,6 +580,10 @@ Server.prototype.closeAllConnections = function() {
573580
};
574581

575582
Server.prototype.closeIdleConnections = function() {
583+
if (!this[kConnections]) {
584+
return;
585+
}
586+
576587
const connections = this[kConnections].idle();
577588

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

lib/https.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -96,8 +96,9 @@ function Server(opts, requestListener) {
9696

9797
this.timeout = 0;
9898
this.maxHeadersCount = null;
99-
setupConnectionsTracking(this);
99+
this.on('listening', setupConnectionsTracking);
100100
}
101+
101102
ObjectSetPrototypeOf(Server.prototype, tls.Server.prototype);
102103
ObjectSetPrototypeOf(Server, tls.Server);
103104

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+
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+
setImmediate(() => {
23+
global.gc();
24+
});
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+
setImmediate(() => {
28+
global.gc();
29+
});

0 commit comments

Comments
 (0)