-
Notifications
You must be signed in to change notification settings - Fork 30.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
http2 sessions aren't cleaned up properly, server can't close #18176
Comments
Will investigate :-) |
I'm unable to reproduce any problem locally and the server close callbacks are being invoked. I've extended a couple of somewhat randomly selected tests and added server.close checks. Running CI now. |
The CI run for 18182 is green with at least 4 tests that check that server.close() callbacks are being fired so things appear to be working correctly. Can I ask you to put together a more complete test case that reliably demonstrates the issue? |
Yuck, that's terrible, I'm starting to think it could be on my side, but it only appears on 9.4, and there was a pretty substancial rewrite of things there, so it's most likely related at least... It could also be a misunderstanding of mine about how the session flow really did/does work. I'll try to pin down and bisect when this happens and what exactly is causing it so that I can write a minimal reproducable test, but as we know, from a complex code base, it's sometimes easier said than done. |
I can see with my system monitor (and some sleeps before and after I close my client session) that when I Could be that I have event handlers registered, I do register handlers for practically all events... I would expect them to be de-registered as I destroy the session though, and the socket to be closed. That's an idea anyway as to what could be the reasons for this. I'll keep investigating an isolated example. |
Can't reproduce with a minimal client, but surely, when I setup an external server and run my unit test against it, it is the client that doesn't close the socket on |
In general, with the changes introduced in 9.4, |
The server stops correctly, if there are no sessions. But if you make a request, do not close the browser and afterwards try to close the server, nothing will happen: const http2 = require('http2');
const fs = require('fs');
const server2 = http2.createSecureServer({
key: fs.readFileSync('./localhost-privkey.pem'),
cert: fs.readFileSync('./localhost-cert.pem')
});
let count = 0;
server2.on('stream', (stream, headers) => {
if (count) {
console.log('Closing...');
server2.close(() => {
console.log('Closed'); // Don't fire
});
}
stream.respond({
'content-type': 'application/json',
':status': 200
});
stream.end('test');
count++;
});
server2.listen(3000); Macos 10.13.2 (17C205) - nodejs 9.4.0 |
The reason for that is because |
Not sure what's going on, but I see that pushed frames won't work since 9.4 either. On a client session, I register a listener for Don't know if this is a timing issue or what, but 9.4 certainly changed everything. All my unit tests passed in Is there a way to perform a kind of |
const sessions = [];
server.on('session', session => {
sessions.push(session);
});
// after several requests
for (const session of sessions) {
session.destroy();
}
server.close(fn) // does not work |
@askuzminov yeah that's practically what I do in |
Verify that server close callbacks are being called PR-URL: nodejs#18182 Refs: nodejs#18176 Reviewed-By: Anna Henningsen <[email protected]> Reviewed-By: Ruben Bridgewater <[email protected]>
Verify that server close callbacks are being called PR-URL: #18182 Refs: #18176 Reviewed-By: Anna Henningsen <[email protected]> Reviewed-By: Ruben Bridgewater <[email protected]>
Verify that server close callbacks are being called PR-URL: #18182 Refs: #18176 Reviewed-By: Anna Henningsen <[email protected]> Reviewed-By: Ruben Bridgewater <[email protected]>
Verify that server close callbacks are being called PR-URL: nodejs#18182 Refs: nodejs#18176 Reviewed-By: Anna Henningsen <[email protected]> Reviewed-By: Ruben Bridgewater <[email protected]>
Verify that server close callbacks are being called Backport-PR-URL: #20456 PR-URL: #18182 Refs: #18176 Reviewed-By: Anna Henningsen <[email protected]> Reviewed-By: Ruben Bridgewater <[email protected]>
Verify that server close callbacks are being called PR-URL: nodejs#18182 Refs: nodejs#18176 Reviewed-By: Anna Henningsen <[email protected]> Reviewed-By: Ruben Bridgewater <[email protected]>
I believe this is resolved. We can reopen the issue if not. |
9.4 (most likely #17406) broke my unit tests in
fetch-h2
, sessions not being closed/destroyed properly anymore. I tried to callclose( )
beforedestroy( )
on my sessions, which would cause horrible code to support older Node.js versions:but that didn't help.
Case:
My unit tests create a server and a client, does things, and then cleans up the client and server connections by terminating their corresponding sessions using
session.destroy( )
. Finally, I wait for the server to be closed, usingserver.close( resolve );
(in a promise constructor as you see). This now fails - the close callback of the server is never called. According to its spec, it'll be called when all connections are gone, so I suspect the sessions aren't cleaned up properly whendestroy( )
is called.Do you have any unit tests in Node.js that does something similar - expecting sessions to actually be cleaned up, and/or for an (H2) server's
close(cb)
to actually call its callback? Otherwise, I'd strongly recommend having such.I don't have time (right now) to write a minimal code example for this, but might be able to do so eventually.
Before
http2
exits its experimental status, I'd also prefer a condensed paragraph in the docs of the lifecycle management of servers, sessions and streams. It's now spread out to all different functions, callbacks and events in the very large documentation page, making an overview of the lifecycles extremely hard to grasp, and getting the lifecycle handling right is key to us users to be able to write robust code.The text was updated successfully, but these errors were encountered: