Skip to content

Commit e1fc9b9

Browse files
akukasBridgeAR
authored andcommitted
http2: do not register unnecessary listeners
PR-URL: #27987 Reviewed-By: Anna Henningsen <[email protected]> Reviewed-By: Ruben Bridgewater <[email protected]> Reviewed-By: James M Snell <[email protected]>
1 parent 79a8cd0 commit e1fc9b9

File tree

2 files changed

+52
-1
lines changed

2 files changed

+52
-1
lines changed

lib/internal/http2/core.js

+11-1
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,7 @@ const kLocalSettings = Symbol('local-settings');
161161
const kOptions = Symbol('options');
162162
const kOwner = owner_symbol;
163163
const kOrigin = Symbol('origin');
164+
const kPendingRequestCalls = Symbol('kPendingRequestCalls');
164165
const kProceed = Symbol('proceed');
165166
const kProtocol = Symbol('protocol');
166167
const kRemoteSettings = Symbol('remote-settings');
@@ -1417,6 +1418,7 @@ class ServerHttp2Session extends Http2Session {
14171418
class ClientHttp2Session extends Http2Session {
14181419
constructor(options, socket) {
14191420
super(NGHTTP2_SESSION_CLIENT, options, socket);
1421+
this[kPendingRequestCalls] = null;
14201422
}
14211423

14221424
// Submits a new HTTP2 request to the connected peer. Returns the
@@ -1486,7 +1488,15 @@ class ClientHttp2Session extends Http2Session {
14861488

14871489
const onConnect = requestOnConnect.bind(stream, headersList, options);
14881490
if (this.connecting) {
1489-
this.once('connect', onConnect);
1491+
if (this[kPendingRequestCalls] !== null) {
1492+
this[kPendingRequestCalls].push(onConnect);
1493+
} else {
1494+
this[kPendingRequestCalls] = [onConnect];
1495+
this.once('connect', () => {
1496+
this[kPendingRequestCalls].forEach((f) => f());
1497+
this[kPendingRequestCalls] = null;
1498+
});
1499+
}
14901500
} else {
14911501
onConnect();
14921502
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
'use strict';
2+
const common = require('../common');
3+
if (!common.hasCrypto)
4+
common.skip('missing crypto');
5+
const http2 = require('http2');
6+
const EventEmitter = require('events');
7+
8+
// This test ensures that a MaxListenersExceededWarning isn't emitted if
9+
// more than EventEmitter.defaultMaxListeners requests are started on a
10+
// ClientHttp2Session before it has finished connecting.
11+
12+
process.on('warning', common.mustNotCall('A warning was emitted'));
13+
14+
const server = http2.createServer();
15+
server.on('stream', (stream) => {
16+
stream.respond();
17+
stream.end();
18+
});
19+
20+
server.listen(common.mustCall(() => {
21+
const client = http2.connect(`http://localhost:${server.address().port}`);
22+
23+
function request() {
24+
return new Promise((resolve, reject) => {
25+
const stream = client.request();
26+
stream.on('error', reject);
27+
stream.on('response', resolve);
28+
stream.end();
29+
});
30+
}
31+
32+
const requests = [];
33+
for (let i = 0; i < EventEmitter.defaultMaxListeners + 1; i++) {
34+
requests.push(request());
35+
}
36+
37+
Promise.all(requests).then(common.mustCall()).finally(common.mustCall(() => {
38+
server.close();
39+
client.close();
40+
}));
41+
}));

0 commit comments

Comments
 (0)