-
Notifications
You must be signed in to change notification settings - Fork 664
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
Client.destroy() does not always destroy the socket, node hangs on exit #1124
Comments
Can you provide an example to reproduce the problem and include which node version you're using? A connecting or connected socket would always have |
If client.destroy() is called, always destroy the underlying socket so that file descriptor is freed. This matches behavior of node's Socket and Writable. Previous behavior made this conditional on writability of the socket. If the socket wasn't writable, then client.destroy() wouldn't actually destroy the socket, the file descriptor would remain open, and the node process would hang on exit.. It might timeout after 15 minutes, if you're lucky. fixes mscdex#1124
Reproducing the problem can be a bit tough as it essentially requires the socket to end up in a half-open (FIN-WAIT-1) state. Basically:
Most SSH servers will respond to a FIN from a client with a FIN of their own, and when the client receives that FIN, nodejs calls Socket.destroy() automatically. However, if a FIN packet never arrives at the client (dropped packet or server leaves things half-open), the client socket will remain open in a FIN-WAIT-1 state. This leaves the file descriptor open in the nodejs process, and it never exits. Calling The documentation for socket.destroy() states:
My hope is that |
I was under the impression you were only calling |
No worries, I could have been more clear. |
https://github.com/mscdex/ssh2/blob/master/lib/client.js#L1089 Seems as though when |
mscdex#1124 Seems as though the socket can still receive data. If there's a specific reason why destroy isn't called regardless of writable state I'm willing to listen
Client.destroy() will only destroy the underlying socket if is writable. Being able to destroy the socket is important as it frees the file descriptor, otherwise node will hang on shutdown until the socket times out (14-15 minutes, in my case).
I'm able to reproduce this by calling Client.end() just prior to calling Client.destroy(), as the first puts the socket into an unwritable state.
The text was updated successfully, but these errors were encountered: