SSH.NET Library - SshClient.Dispose(), public connection

倖福魔咒の 提交于 2019-12-04 19:45:13

This is a deadlock. button1_Click is running on your UI thread, as is the Invoke inside of DataReceived.

SSH.NET does not internally use async -- all of it's "async" methods simply wrap a sync method in a thread pool and lock.

The flow will be this:

  1. BeginRead grabs hold of the lock and starts reading.
  2. Disconnect waits on the lock, in the UI thread, until `BeginRead is done with it.
  3. BeginRead finishes the read, and calls DataReceived which calls Invoke while still holding the lock.
  4. Invoke waits for the UI thread to process its message -- but it never will, because the UI thread is waiting on Disconnect.
  5. Now BeginRead and Disconnect are both waiting for each-other to finish -- a deadlock.

A quick way to test this would be to change the Invoke call to BeginInvoke, which will remove the deadlock.

As far as accessing these objects from anywhere in your Form, just make them members of the class.

I also stumbled accross this problem and the way I see it there is no way getting around this without modifying SSH.NET code. There is following block of code in SSH.NET, (Session.cs:584):

ExecuteThread(() =>
                    {
                        try
                        {
                            MessageListener();
                        }
                        finally
                        {
                            _messageListenerCompleted.Set();
                        }
                    });

This leads to following block of code(Session.NET.cs:220):

partial void SocketRead(int length, ref byte[] buffer)
..
catch (SocketException exp) {
if (exp.SocketErrorCode == SocketError.ConnectionAborted)    
{
      buffer = new byte[length];
      Disconnect();

inside disconnect it waits for _messageListenerCompleted.WaitOne() But this can never happen because _messageListenerCompleted.Set() is called in try{}finally{} block. So to solve this we should either call: _messageListenerCompleted.Set() before calling disconnect() during socket exception or handling Dissconnect somewhere outside

  SocketRead(int length, ref byte[] buffer)

function.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!