mirror of
https://github.com/nodejs/node.git
synced 2026-11-09 15:11:11 -05:00
http2: clear the session timeout before marking it destroyed
closeSession() set SESSION_FLAGS_DESTROYED and then called session.setTimeout(0). setStreamTimeout() returns early when the session is destroyed, so the idle timer stayed armed and retained the session until the server timeout fired. Clear the timeout and remove its listeners before setting the destroyed flag. Fixes: https://github.com/nodejs/node/issues/66885 Signed-off-by: huang <13165998033@163.com> PR-URL: https://github.com/nodejs/node/pull/66886 Reviewed-By: Tim Perry <pimterry@gmail.com>
This commit is contained in:
1 parent
0fc31021c1
commit
663f666fda
3 files changed
+76
-3
No files matched your search
@@ -1303,13 +1303,16 @@ function closeSession(session, code, error) {
|
||||
debugSessionObj(session, 'start closing/destroying', error);
|
||||
|
||||
const state = session[kState];
|
||||
state.flags |= SESSION_FLAGS_DESTROYED;
|
||||
state.destroyCode = code;
|
||||
|
||||
// Clear timeout and remove timeout listeners.
|
||||
// Clear timeout and remove timeout listeners before marking the session
|
||||
// destroyed: setTimeout() is a no-op once destroyed, so the idle timer
|
||||
// would otherwise stay armed and retain the session.
|
||||
session.setTimeout(0);
|
||||
session.removeAllListeners('timeout');
|
||||
|
||||
state.flags |= SESSION_FLAGS_DESTROYED;
|
||||
state.destroyCode = code;
|
||||
|
||||
const socket = session[kSocket];
|
||||
const handle = session[kHandle];
|
||||
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
'use strict';
|
||||
|
||||
const common = require('../common');
|
||||
if (!common.hasCrypto)
|
||||
common.skip('missing crypto');
|
||||
const assert = require('assert');
|
||||
const http2 = require('http2');
|
||||
const net = require('net');
|
||||
|
||||
// Same as test-http2-session-timeout-cleared-on-close.js, but the client's
|
||||
// TCP socket is destroyed without sending GOAWAY.
|
||||
const server = http2.createServer();
|
||||
server.setTimeout(30_000, common.mustNotCall());
|
||||
|
||||
server.on('session', common.mustCall((session) => {
|
||||
session.on('goaway', common.mustNotCall());
|
||||
session.on('close', common.mustCall(() => {
|
||||
assert.strictEqual(session.timeout, 0);
|
||||
server.close();
|
||||
}));
|
||||
}));
|
||||
|
||||
server.on('stream', common.mustCall((stream) => {
|
||||
stream.respond({ ':status': 200 });
|
||||
stream.end('ok');
|
||||
}));
|
||||
|
||||
server.listen(0, common.mustCall(() => {
|
||||
let socket;
|
||||
const client = http2.connect(`http://localhost:${server.address().port}`, {
|
||||
createConnection: (url) => (socket = net.connect(url.port, url.hostname)),
|
||||
});
|
||||
client.on('error', () => {});
|
||||
const req = client.request();
|
||||
req.on('error', () => {});
|
||||
req.resume();
|
||||
req.on('end', common.mustCall(() => socket.destroy()));
|
||||
}));
|
||||
@@ -0,0 +1,32 @@
|
||||
'use strict';
|
||||
|
||||
const common = require('../common');
|
||||
if (!common.hasCrypto)
|
||||
common.skip('missing crypto');
|
||||
const assert = require('assert');
|
||||
const http2 = require('http2');
|
||||
|
||||
// A destroyed session must not keep its idle timer armed: setTimeout() is a
|
||||
// no-op once the session is marked destroyed, so closeSession() has to clear
|
||||
// the timer first.
|
||||
const server = http2.createServer();
|
||||
server.setTimeout(30_000, common.mustNotCall());
|
||||
|
||||
server.on('session', common.mustCall((session) => {
|
||||
session.on('close', common.mustCall(() => {
|
||||
assert.strictEqual(session.timeout, 0);
|
||||
server.close();
|
||||
}));
|
||||
}));
|
||||
|
||||
server.on('stream', common.mustCall((stream) => {
|
||||
stream.respond({ ':status': 200 });
|
||||
stream.end('ok');
|
||||
}));
|
||||
|
||||
server.listen(0, common.mustCall(() => {
|
||||
const client = http2.connect(`http://localhost:${server.address().port}`);
|
||||
const req = client.request();
|
||||
req.resume();
|
||||
req.on('end', common.mustCall(() => client.close()));
|
||||
}));
|
||||
Reference in new issue
Block a user