-
-
Notifications
You must be signed in to change notification settings - Fork 2.4k
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
Unable to properly cleanup underlying socket with close/terminate #1869
Comments
It is indeed odd but this behavior is defined by Node.js core not const http = require('http');
const net = require('net');
const request = http.get({
port: 4987,
createConnection: net.connect,
headers: {
'Sec-WebSocket-Version': 13,
'Sec-WebSocket-Key': 'rHat1v1OTJosG31ChyAUVA==',
Connection: 'Upgrade',
Upgrade: 'websocket'
}
});
request.on('response', function (response) {
response.on('end', function () {
console.log('done');
request.abort();
});
response.resume();
}); This used to work as expected before nodejs/node@b04e884. Also, the request does not use an agent so the connection should not be kept alive. However the |
Something like this diff --git a/lib/websocket.js b/lib/websocket.js
index 0e2a83d..aa47fab 100644
--- a/lib/websocket.js
+++ b/lib/websocket.js
@@ -718,6 +718,11 @@ function abortHandshake(websocket, stream, message) {
if (stream.setHeader) {
stream.abort();
+
+ if (stream.socket && !stream.socket.destroyed) {
+ stream.socket.destroy();
+ }
+
stream.once('abort', websocket.emitClose.bind(websocket));
websocket.emit('error', err);
} else { should solve the problem and make the behavior consistent on all supported Node.js versions. It seems a bit hacky but I see no other way without reverting nodejs/node@b04e884 or documenting that What do you think? |
I see and yes i do agree, i wasn't aware of the behavior change caused by nodejs/node@b04e884 The reason i raised this "question" is that "not knowing" the underlying socket could end up being kept alive (which likely includes majority of the users of this library) can have catastrophic consequences in certain scenarios when "rapid reconnect" due to connection failure is necessary. |
I think this is a rare edge case because it depends on:
so in my opinion it would be sufficient to document that in this case The above patch also has the side effect of preventing the socket from being reused, or worse destroying the socket of another request if a keep-alive agent is used. However this is how it worked before Node.js 14.3.0 and consistency is nice. |
I agree it is quite rate (one of the reasons why it took me so long to run into this). To give you a real world example (which is definitely on the rare side):
Eventually the client system OOMed due to holding on to all the underlying sockets/resources. The bottom line is, i am completely fine with either approach/just trying to find a reasonable way to prevent others from running into similar scenario, as the back end server returning "unexpected garbage" due to technical issues can be quite common. |
Description
Hi Luigi, i am a bit lost if this a valid edge case to report. but i do find it "odd" that reading the payload from the response (while doing such successfully) can result in the underlying socket being left open).
Calling the
request.socket.destroy();
after response end event fires bypasses the problem.Is this behavior expected from your point of view?
Reproducible in:
Steps to reproduce:
Demo server (returning invalid data on purpose):
Client demonstrating the issue:
Expected result:
With the demo client code above, the bottom line is that the node process shuts down on its own.
Actual result:
The demo client code did not shut down because the underlying TCP sockets are left in
ESTABLISHED
state.Regardless of calling ws.close() or ws.terminate().
The "trigger" for the above scenario appears to be binding the additional event handlers used to read the response payload (which does succeeds).
You can confirm that the connections are left open by doing
netstat -an | grep ':4987' | grep ESTABLISHED | wc -l
The text was updated successfully, but these errors were encountered: