Jelajahi Sumber

Swallow ObjectDisposed on SFTP wait handle when receiving late response (#1531)

Rob Hague 11 bulan lalu
induk
melakukan
c28f02301f
2 mengubah file dengan 51 tambahan dan 36 penghapusan
  1. 18 0
      src/Renci.SshNet/Common/Extensions.cs
  2. 33 36
      src/Renci.SshNet/Sftp/SftpSession.cs

+ 18 - 0
src/Renci.SshNet/Common/Extensions.cs

@@ -7,6 +7,7 @@ using System.Net.Sockets;
 using System.Numerics;
 using System.Runtime.CompilerServices;
 using System.Text;
+using System.Threading;
 
 using Renci.SshNet.Abstractions;
 using Renci.SshNet.Messages;
@@ -120,6 +121,23 @@ namespace Renci.SshNet.Common
             return target;
         }
 
+        /// <summary>
+        /// Sets a wait handle, swallowing any resulting <see cref="ObjectDisposedException"/>.
+        /// Used in cases where set and dispose may race.
+        /// </summary>
+        /// <param name="waitHandle">The wait handle to set.</param>
+        public static void SetIgnoringObjectDisposed(this EventWaitHandle waitHandle)
+        {
+            try
+            {
+                _ = waitHandle.Set();
+            }
+            catch (ObjectDisposedException)
+            {
+                // ODE intentionally ignored.
+            }
+        }
+
         /// <summary>
         /// Reverses the sequence of the elements in the entire one-dimensional <see cref="Array"/>.
         /// </summary>

+ 33 - 36
src/Renci.SshNet/Sftp/SftpSession.cs

@@ -492,12 +492,12 @@ namespace Renci.SshNet.Sftp
                                                   response =>
                                                   {
                                                       handle = response.Handle;
-                                                      _ = wait.Set();
+                                                      wait.SetIgnoringObjectDisposed();
                                                   },
                                                   response =>
                                                   {
                                                       exception = GetSftpException(response);
-                                                      _ = wait.Set();
+                                                      wait.SetIgnoringObjectDisposed();
                                                   });
 
                 SendRequest(request);
@@ -625,7 +625,7 @@ namespace Renci.SshNet.Sftp
                                                    response =>
                                                    {
                                                        exception = GetSftpException(response);
-                                                       _ = wait.Set();
+                                                       wait.SetIgnoringObjectDisposed();
                                                    });
 
                 SendRequest(request);
@@ -825,7 +825,7 @@ namespace Renci.SshNet.Sftp
                                                   response =>
                                                   {
                                                       data = response.Data;
-                                                      _ = wait.Set();
+                                                      wait.SetIgnoringObjectDisposed();
                                                   },
                                                   response =>
                                                   {
@@ -838,7 +838,7 @@ namespace Renci.SshNet.Sftp
                                                           data = Array.Empty<byte>();
                                                       }
 
-                                                      _ = wait.Set();
+                                                      wait.SetIgnoringObjectDisposed();
                                                   });
 
                 SendRequest(request);
@@ -928,10 +928,7 @@ namespace Renci.SshNet.Sftp
                                                    writeCompleted?.Invoke(response);
 
                                                    exception = GetSftpException(response);
-                                                   if (wait != null)
-                                                   {
-                                                       _ = wait.Set();
-                                                   }
+                                                   wait?.SetIgnoringObjectDisposed();
                                                });
 
             SendRequest(request);
@@ -1011,12 +1008,12 @@ namespace Renci.SshNet.Sftp
                                                    response =>
                                                    {
                                                        attributes = response.Attributes;
-                                                       _ = wait.Set();
+                                                       wait.SetIgnoringObjectDisposed();
                                                    },
                                                    response =>
                                                    {
                                                        exception = GetSftpException(response);
-                                                       _ = wait.Set();
+                                                       wait.SetIgnoringObjectDisposed();
                                                    });
 
                 SendRequest(request);
@@ -1140,12 +1137,12 @@ namespace Renci.SshNet.Sftp
                                                    response =>
                                                    {
                                                        attributes = response.Attributes;
-                                                       _ = wait.Set();
+                                                       wait.SetIgnoringObjectDisposed();
                                                    },
                                                    response =>
                                                    {
                                                        exception = GetSftpException(response);
-                                                       _ = wait.Set();
+                                                       wait.SetIgnoringObjectDisposed();
                                                    });
 
                 SendRequest(request);
@@ -1207,7 +1204,7 @@ namespace Renci.SshNet.Sftp
                                                      response =>
                                                      {
                                                          exception = GetSftpException(response);
-                                                         _ = wait.Set();
+                                                         wait.SetIgnoringObjectDisposed();
                                                      });
 
                 SendRequest(request);
@@ -1239,7 +1236,7 @@ namespace Renci.SshNet.Sftp
                                                       response =>
                                                       {
                                                           exception = GetSftpException(response);
-                                                          _ = wait.Set();
+                                                          wait.SetIgnoringObjectDisposed();
                                                       });
 
                 SendRequest(request);
@@ -1274,12 +1271,12 @@ namespace Renci.SshNet.Sftp
                                                      response =>
                                                      {
                                                          handle = response.Handle;
-                                                         _ = wait.Set();
+                                                         wait.SetIgnoringObjectDisposed();
                                                      },
                                                      response =>
                                                      {
                                                          exception = GetSftpException(response);
-                                                         _ = wait.Set();
+                                                         wait.SetIgnoringObjectDisposed();
                                                      });
 
                 SendRequest(request);
@@ -1345,7 +1342,7 @@ namespace Renci.SshNet.Sftp
                                                      response =>
                                                      {
                                                          result = response.Files;
-                                                         _ = wait.Set();
+                                                         wait.SetIgnoringObjectDisposed();
                                                      },
                                                      response =>
                                                      {
@@ -1354,7 +1351,7 @@ namespace Renci.SshNet.Sftp
                                                              exception = GetSftpException(response);
                                                          }
 
-                                                         _ = wait.Set();
+                                                         wait.SetIgnoringObjectDisposed();
                                                      });
 
                 SendRequest(request);
@@ -1426,7 +1423,7 @@ namespace Renci.SshNet.Sftp
                                                     response =>
                                                     {
                                                         exception = GetSftpException(response);
-                                                        _ = wait.Set();
+                                                        wait.SetIgnoringObjectDisposed();
                                                     });
 
                 SendRequest(request);
@@ -1493,7 +1490,7 @@ namespace Renci.SshNet.Sftp
                                                    response =>
                                                    {
                                                        exception = GetSftpException(response);
-                                                       _ = wait.Set();
+                                                       wait.SetIgnoringObjectDisposed();
                                                    });
 
                 SendRequest(request);
@@ -1558,7 +1555,7 @@ namespace Renci.SshNet.Sftp
                                                    response =>
                                                    {
                                                        exception = GetSftpException(response);
-                                                       _ = wait.Set();
+                                                       wait.SetIgnoringObjectDisposed();
                                                    });
 
                 SendRequest(request);
@@ -1625,12 +1622,12 @@ namespace Renci.SshNet.Sftp
                                                       response =>
                                                       {
                                                           result = response.Files;
-                                                          _ = wait.Set();
+                                                          wait.SetIgnoringObjectDisposed();
                                                       },
                                                       response =>
                                                       {
                                                           exception = GetSftpException(response);
-                                                          _ = wait.Set();
+                                                          wait.SetIgnoringObjectDisposed();
                                                       });
 
                 SendRequest(request);
@@ -1751,12 +1748,12 @@ namespace Renci.SshNet.Sftp
                                                   response =>
                                                   {
                                                       attributes = response.Attributes;
-                                                      _ = wait.Set();
+                                                      wait.SetIgnoringObjectDisposed();
                                                   },
                                                   response =>
                                                   {
                                                       exception = GetSftpException(response);
-                                                      _ = wait.Set();
+                                                      wait.SetIgnoringObjectDisposed();
                                                   });
 
                 SendRequest(request);
@@ -1849,7 +1846,7 @@ namespace Renci.SshNet.Sftp
                                                     response =>
                                                     {
                                                         exception = GetSftpException(response);
-                                                        _ = wait.Set();
+                                                        wait.SetIgnoringObjectDisposed();
                                                     });
 
                 SendRequest(request);
@@ -1930,12 +1927,12 @@ namespace Renci.SshNet.Sftp
                                                       response =>
                                                       {
                                                           result = response.Files;
-                                                          _ = wait.Set();
+                                                          wait.SetIgnoringObjectDisposed();
                                                       },
                                                       response =>
                                                       {
                                                           exception = GetSftpException(response);
-                                                          _ = wait.Set();
+                                                          wait.SetIgnoringObjectDisposed();
                                                       });
 
                 SendRequest(request);
@@ -1975,7 +1972,7 @@ namespace Renci.SshNet.Sftp
                                                      response =>
                                                      {
                                                          exception = GetSftpException(response);
-                                                         _ = wait.Set();
+                                                         wait.SetIgnoringObjectDisposed();
                                                      });
 
                 SendRequest(request);
@@ -2013,7 +2010,7 @@ namespace Renci.SshNet.Sftp
                                                      response =>
                                                      {
                                                          exception = GetSftpException(response);
-                                                         _ = wait.Set();
+                                                         wait.SetIgnoringObjectDisposed();
                                                      });
 
                 if (!_supportedExtensions.ContainsKey(request.Name))
@@ -2060,12 +2057,12 @@ namespace Renci.SshNet.Sftp
                                                  response =>
                                                  {
                                                      information = response.GetReply<StatVfsReplyInfo>().Information;
-                                                     _ = wait.Set();
+                                                     wait.SetIgnoringObjectDisposed();
                                                  },
                                                  response =>
                                                  {
                                                      exception = GetSftpException(response);
-                                                     _ = wait.Set();
+                                                     wait.SetIgnoringObjectDisposed();
                                                  });
 
                 if (!_supportedExtensions.ContainsKey(request.Name))
@@ -2148,12 +2145,12 @@ namespace Renci.SshNet.Sftp
                                                   response =>
                                                   {
                                                       information = response.GetReply<StatVfsReplyInfo>().Information;
-                                                      _ = wait.Set();
+                                                      wait.SetIgnoringObjectDisposed();
                                                   },
                                                   response =>
                                                   {
                                                       exception = GetSftpException(response);
-                                                      _ = wait.Set();
+                                                      wait.SetIgnoringObjectDisposed();
                                                   });
 
                 if (!_supportedExtensions.ContainsKey(request.Name))
@@ -2197,7 +2194,7 @@ namespace Renci.SshNet.Sftp
                                                   response =>
                                                   {
                                                       exception = GetSftpException(response);
-                                                      _ = wait.Set();
+                                                      wait.SetIgnoringObjectDisposed();
                                                   });
 
                 if (!_supportedExtensions.ContainsKey(request.Name))