What happens when the object is disposed that would cause a later, new connection to disconnect?

Advertisement

BananaCabbage
Joined:
Posts:
3

What happens when the object is disposed that would cause a later, new connection to disconnect?

I was having an issue with random disconnections with some code I put together. This code was creating a new FTP session with the "Using" command which meant the session was disposed after every transfer.
I noticed that around 1-2 mins after the original session was disposed, I would get disconnected on the next transfer. I decided this was the wrong way to do things anyway and rewrote it to use a single session for everything.

This has worked fine, but now I wanted to implement something so that if a transfer failed for some reason, we would dispose the whole thing, and create a new session and try again. I'm back to the same issue that the dispose seems to cause the next transfer to be killed about 70 seconds in. I can and have mitigated this, by delaying any subsequent transfers by 2 minutes and this has worked around the issue. This is clearly far from ideal. What is happening with the session.dispose that causes the next transfer to fail about 70 seconds in?

Here's some code:
static public void DownloadThread(string IPAdd, int ThreadNum)
{
   Session session;
   session = OpenSession(IPAdd, ThreadNum);
   //Kick out if the session isn't opened.
   if (!session.Opened)
   {
      Log("Unable to Connect to " + IPAdd, ThreadNum);
      abortThread(ThreadNum);
   }
 
   Log("Sending file to IP: " + IPAdd, ThreadNum);
   string filename = Path.GetFileName(Globals.FileToSend);
   string result = FTPSendFile(IPAdd, Globals.FileToSend, Globals.RemoteLocation, ThreadNum, filename, session);
 
   if (result.Contains("226"))
   {
      Log("File upload completed and verified!", ThreadNum);
   }
   else
   {
      Log("File upload Failed! Killing thread.", ThreadNum);
      abortThread(ThreadNum);
   }
   
   session.Dispose();
} 
 
 
 private static Session OpenSession(string IP, int ThreadNum)
{
   // Setup session options
   SessionOptions sessionOptions = new SessionOptions
   {
      Protocol = Protocol.Ftp,
      HostName = IP,
      UserName = "anonymous",
      Password = "anonymous@example.com",
      TimeoutInMilliseconds = 3600000
   };
   
   Session session = new Session();
   session.FileTransferProgress += (sender, e) => SessionFileTransferProgress(sender, e, ThreadNum);
   session.Open(sessionOptions);
   return session;
}
 
 static public string FTPSendFile(string IP, string LocalFile, string remoteFileLocation, int ThreadNum, string FinalFileName, Session session)
{
   currentFileUploading = FinalFileName;
   string fullRemoteFileName = remoteFileLocation + FinalFileName;
   int RetryAttempts = 3;
 
 
   while (RetryAttempts > 0)
   {
      TransferOptions transferOptions = new TransferOptions();
      transferOptions.TransferMode = TransferMode.Binary;
 
      try
      {
         TransferOperationResult transferResult;
         transferResult = session.PutFiles(LocalFile, fullRemoteFileName, false, transferOptions);
         transferResult.Check(); //Triggers the execption
      }
      catch (Exception e)
      {
         System.Diagnostics.Debug.WriteLine("Upload of {0} logged as failure, due to {1}", LocalFile, e);
      }
 
      //Check does remote file match local file.
      long RemoteFilesizeBytes = session.GetFileInfo(fullRemoteFileName).Length;
      //Get local file size
      FileInfo fileInfo = new FileInfo(LocalFile);
      long LocalFileSize = fileInfo.Length;
 
      if (RemoteFilesizeBytes == LocalFileSize)
      {
      return "226";
      }
 
      //If we get here something went wrong.
      session.Dispose();
 
      if (RetryAttempts > 1)
      {
         Log("Error during download, " + RetryAttempts.ToString() + " retries left.", ThreadNum);
      }
      else if(RetryAttempts == 1)
      {
         Log("Error during download, " + RetryAttempts.ToString() + " retry left.", ThreadNum);
      }
      else
      {
         Log("Error during download, no retries remain. Abort",ThreadNum);
      }
      Thread.Sleep(30000);
 
      session = OpenSession(IP,ThreadNum);
      //Kick out if the session isn't opened.
      if (!session.Opened)
      {
         Log("Abort: unable to reconnect to " + IP, ThreadNum);
         abortThread(ThreadNum);
      }
 
   }
   return "Error: Download failed, out of retries.";
}

Reply with quote

Advertisement

martin
Site Admin
martin avatar
Joined:
Posts:
40,587
Location:
Prague, Czechia

Re: What happens when the object is disposed that would cause a later, new connection to disconnect?

I do not think this has anything to do with your code or WinSCP. Consider checking server-side logs.
If you want us to investigate anyway, please post WinSCP session log files.

Reply with quote

BananaCabbage
Joined:
Posts:
3

Hi Martin,

Unfortunately the server side is a closed source PLC with no logs that we can access.

I've been trying to get a clean log of the issue for the last few days, but I keep having various issues with the server side that are making it difficult.

The thing is, if we wait 2 minutes it *always* works. I'm going with this solution for now, as it's only when a download fails, which should be a rare occurrence and I've spent too much time trying to dubug this already.

Thanks for your help anyway.

Reply with quote

Advertisement

You can post new topics in this forum