ssh-3.0, ssh_connection_handler.erl Incorrect processing shutdown

Alexander Demidenko <[email protected]> Thu, 23 Jan 2014 15:49:13 +0700
Newsgroups gmane.comp.lang.erlang.patches
Message-ID <CAN0YpQ9WHWCbU6_s9JUHy-7vA_dbeKbYqx-3oJv3Fe4p5ghySg@mail.gmail.com>
Hello, friends!

ssh-3.0 (and below) has the following bug:
If we have a lot of SSH sessions, we will be much more timeout. (4 seconds
per each instance).

When trying to complete the ssh-application, process, was created by a call
ssh_connection_handler:init/1, receives a message of the form {'EXIT', Pid,
shutdown}. After receiving this message, will been completed a series of
calls ssh_connetion_handler:terminate, which ends the call
ssh_connetion_handler:terminate_subsystem/1->ssh_system_sup:stop_subsystem/2
. At the end of the chain calls the supervisor:which_children (SystemSup).
In this place there is a deadlock, because SystemSup process awaits the
completion message.  Since SystemSup not receive the completion message, it
completes them forcibly by timeout (after 4 second)

How can I see, in the ssh_connection_handler.erl module, invalid method
terminate by initiative supervisor. In case of shutdown, we must not call
terminate_subsytem/1

Suggest a patch that fixes this problem :

--- src/ssh_connection_handler.erl
+++ src/ssh_connection_handler.erl
@@ -904,26 +904,31 @@
                 socket = Socket}) ->
     terminate_subsytem(Connection),
     (catch Transport:close(Socket)),
     ok;

 %% Terminated by supervisor
-terminate(shutdown, StateName, #state{ssh_params = Ssh0} = State) ->
+terminate(shutdown, _StateName, #state{ssh_params = Ssh0,
+                                       transport_cb = Transport,
+                           socket = Socket} = State) ->
     DisconnectMsg =
     #ssh_msg_disconnect{code = ?SSH_DISCONNECT_BY_APPLICATION,
                 description = "Application shutdown",
                 language = "en"},
-    {SshPacket, Ssh} = ssh_transport:ssh_packet(DisconnectMsg, Ssh0),
+    {SshPacket, _Ssh} = ssh_transport:ssh_packet(DisconnectMsg, Ssh0),
     send_msg(SshPacket, State),
-    terminate(normal, StateName, State#state{ssh_params = Ssh});
+    (catch Transport:close(Socket)),
+    ok;

 terminate({shutdown, #ssh_msg_disconnect{} = Msg}, StateName,
       #state{ssh_params = Ssh0} = State) ->
      {SshPacket, Ssh} = ssh_transport:ssh_packet(Msg, Ssh0),
     send_msg(SshPacket, State),


-- 
---------------------------------------------
With best regards,
Alexander.

_______________________________________________
erlang-patches mailing list
[email protected]
http://erlang.org/mailman/listinfo/erlang-patches
ssh_3.patch (text/x-patch, 1.1 KB)
--- src/ssh_connection_handler.erl
+++ src/ssh_connection_handler.erl
@@ -904,26 +904,31 @@
 			    socket = Socket}) ->
     terminate_subsytem(Connection),
     (catch Transport:close(Socket)),
     ok;
 
 %% Terminated by supervisor
-terminate(shutdown, StateName, #state{ssh_params = Ssh0} = State) ->
+terminate(shutdown, _StateName, #state{ssh_params = Ssh0, 
+                                       transport_cb = Transport,
+			               socket = Socket} = State) ->
     DisconnectMsg = 
 	#ssh_msg_disconnect{code = ?SSH_DISCONNECT_BY_APPLICATION,
 			    description = "Application shutdown",
 			    language = "en"},
-    {SshPacket, Ssh} = ssh_transport:ssh_packet(DisconnectMsg, Ssh0),
+    {SshPacket, _Ssh} = ssh_transport:ssh_packet(DisconnectMsg, Ssh0),
     send_msg(SshPacket, State),
-    terminate(normal, StateName, State#state{ssh_params = Ssh});
+    (catch Transport:close(Socket)),
+    ok;
 
 terminate({shutdown, #ssh_msg_disconnect{} = Msg}, StateName,
 	  #state{ssh_params = Ssh0} = State) ->
      {SshPacket, Ssh} = ssh_transport:ssh_packet(Msg, Ssh0),
     send_msg(SshPacket, State),