libssh2会话清理没有阻塞?

时间:2012-10-19 19:27:16

标签: c libssh

我的应用程序使用libssh2通过SSH进行通信,通常可以正常工作。我遇到的一个问题是远程主机意外死机 - 在这种情况下,远程主机是一个可能随时断电的嵌入式设备,因此这种情况并不罕见。

当发生这种情况时,我的应用检测到远程计算机已停止响应ping,并断开SSH连接的本地端,如下所示:

void SSHSession :: CleanupSession()
{
   if (_uploadFileChannel)
   {
      libssh2_channel_free(_uploadFileChannel);
      _uploadFileChannel = NULL;
   }

   if (_sendCommandsChannel)
   {
      libssh2_channel_free(_sendCommandsChannel);
      _sendCommandsChannel = NULL;
   }

   if (_session)
   {
      libssh2_session_disconnect(_session, "bye bye");
      libssh2_session_free(_session);
      _session = NULL;
   }
}

非常简单,但问题是libssh2_channel_free()调用可能会长时间阻塞,等待远程端响应“我现在要离开”消息,因为它已断电而永远不会这样做...但与此同时,我的应用程序被冻结(在清理程序中被阻止),这是不好的。

有没有办法(缺少黑客libssh2)来避免这种情况?我想拆掉本地SSH数据结构,在此拆除过程中永远不会阻塞。 (我想我可以简单地泄漏SSH会话内存,或者将它委托给另一个线程,但这些似乎是丑陋的黑客而不是正确的解决方案)

2 个答案:

答案 0 :(得分:0)

我对libssh2没有经验,但也许我们可以通过使用libssh2_session_disconnect_ex和不同的断开原因来解决libssh2中的不同行为:SSH_DISCONNECT_CONNECTION_LOST

libssh2_session_disconnect相当于使用libssh2_session_disconnect_ex,原因为SSH_DISCONNECT_BY_APPLICATION。如果libssh2知道连接丢失了,也许它不会尝试与另一方交谈。

http://libssh2.sourceforge.net/doc/#libssh2sessiondisconnectex

http://libssh2.sourceforge.net/doc/#sshdisconnectcodes

答案 1 :(得分:0)

设置为非阻塞模式并通过设置回调函数来控制从套接字读取数据,使用libssh2_session_callback_set和cbstype的LIBSSH2_CALLBACK_RECV从soket读取数据

void *libssh2_session_callback_set(LIBSSH2_SESSION *session, int cbtype, void *callback);

如果由于错误ENOTCONN无法从套接字读取数据,这意味着远程端已关闭套接字或连接失败,则在回调函数中返回-ENOTCONN