Search code examples
c#.netssh.net

ssh.net throw operation session has timed out and get stuck


I created window service that use SSH.net to read file from sFTP server every 600 seconds in OnStart I create timer

timer = new Timer(TimerCallback, null, 0, timeDelay);

and TimerCallBack is function that use SSH.net. In connection before read file I have code to connect to sFTP server like below

            var FILE_READ_FLAG = false;
            try
            {
                req = new SftpClient(ftpHost, ftpLogin, ftpLoginPassword);
                req.Connect();
                if (req.IsConnected)
                {
                    directories = req.ListDirectory(ftpPath);
                    FILE_READ_FLAG = true;
                }
            }
            catch (Exception e)
            {

                EventLog.WriteEntry(sSource,"ERROR : " + GetFullMessageFromException(e), 
                                    EventLogEntryType.Information, 234);
                
                FILE_READ_FLAG = false;
            }
            if (FILE_READ_FLAG){
               // read file and insert to database
            }

the problem is when service run and exception occur the service can run again every 600 seconds but with the error

Session operation has timed out
   at Renci.SshNet.Session.WaitOnHandle(WaitHandle waitHandle, TimeSpan timeout)
   at Renci.SshNet.Session.WaitOnHandle(WaitHandle waitHandle)
   at Renci.SshNet.Session.Connect()
   at Renci.SshNet.BaseClient.Connect()

the service cannot run again and seem to stuck when I try to stop and restart service, Windows show alert message cannot stop in timely fashion and I have to kill service by cmd and start it manually

My question is why another exception can handle with try/catch block but with this error the service not run again with timer what I missing or using it wrong? thank you


Solution

  • You've created an object SftpClient. Looking at the code it does not get disposed properly and also you don't call disconnect. It's possible, if there is an error the system will hang as there is an open connection.

    However you set the client as a variable (i.e req = new SftpClient(ftpHost, ftpLogin, ftpLoginPassword), so its possible the disconnect/ disposed is called elsewhere. Although I'd still recommend re-structuring the code so that you get the data from the SFTP Client and them immediately disconnect/ dispose. It's good practice to minimise the amount of time the connection is open.

    Consider the following:

    List<SftpFile> files = null; 
    using (SftpClient sftp = new SftpClient(host, username, password)) // using will dispose SftpClient
    {
        try
        {
            sftp.Connect();    
            files = sftp.ListDirectory(ftpPath).ToList();    
            sftp.Disconnect();
        }
        catch (Exception e)
        {
            EventLog.WriteEntry(sSource,"ERROR : " + GetFullMessageFromException(e), 
                                    EventLogEntryType.Information, 234);
        }
    }
    
    if(files.any())
    {
       // Process the files.
    }