From b7bf403ba4169f22f8a5c95cf3efd0f9f59ac8a4 Mon Sep 17 00:00:00 2001 From: Rob Hague Date: Sat, 9 Nov 2024 10:58:44 +0100 Subject: [PATCH] Swallow ObjectDisposed on SFTP wait handle when receiving late response --- src/Renci.SshNet/Common/Extensions.cs | 18 +++++++ src/Renci.SshNet/Sftp/SftpSession.cs | 69 +++++++++++++-------------- 2 files changed, 51 insertions(+), 36 deletions(-) diff --git a/src/Renci.SshNet/Common/Extensions.cs b/src/Renci.SshNet/Common/Extensions.cs index 77a8329da..cf4deb077 100644 --- a/src/Renci.SshNet/Common/Extensions.cs +++ b/src/Renci.SshNet/Common/Extensions.cs @@ -7,6 +7,7 @@ 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 @@ public static byte[] ExportKeyParameter(this BigInteger value, int length) return target; } + /// + /// Sets a wait handle, swallowing any resulting . + /// Used in cases where set and dispose may race. + /// + /// The wait handle to set. + public static void SetIgnoringObjectDisposed(this EventWaitHandle waitHandle) + { + try + { + _ = waitHandle.Set(); + } + catch (ObjectDisposedException) + { + // ODE intentionally ignored. + } + } + /// /// Reverses the sequence of the elements in the entire one-dimensional . /// diff --git a/src/Renci.SshNet/Sftp/SftpSession.cs b/src/Renci.SshNet/Sftp/SftpSession.cs index 7fd8888dd..f96b6d306 100644 --- a/src/Renci.SshNet/Sftp/SftpSession.cs +++ b/src/Renci.SshNet/Sftp/SftpSession.cs @@ -492,12 +492,12 @@ public byte[] RequestOpen(string path, Flags flags, bool nullOnError = false) response => { handle = response.Handle; - _ = wait.Set(); + wait.SetIgnoringObjectDisposed(); }, response => { exception = GetSftpException(response); - _ = wait.Set(); + wait.SetIgnoringObjectDisposed(); }); SendRequest(request); @@ -625,7 +625,7 @@ public void RequestClose(byte[] handle) response => { exception = GetSftpException(response); - _ = wait.Set(); + wait.SetIgnoringObjectDisposed(); }); SendRequest(request); @@ -825,7 +825,7 @@ public byte[] RequestRead(byte[] handle, ulong offset, uint length) response => { data = response.Data; - _ = wait.Set(); + wait.SetIgnoringObjectDisposed(); }, response => { @@ -838,7 +838,7 @@ public byte[] RequestRead(byte[] handle, ulong offset, uint length) data = Array.Empty(); } - _ = wait.Set(); + wait.SetIgnoringObjectDisposed(); }); SendRequest(request); @@ -928,10 +928,7 @@ public void RequestWrite(byte[] handle, writeCompleted?.Invoke(response); exception = GetSftpException(response); - if (wait != null) - { - _ = wait.Set(); - } + wait?.SetIgnoringObjectDisposed(); }); SendRequest(request); @@ -1011,12 +1008,12 @@ public SftpFileAttributes RequestLStat(string path) response => { attributes = response.Attributes; - _ = wait.Set(); + wait.SetIgnoringObjectDisposed(); }, response => { exception = GetSftpException(response); - _ = wait.Set(); + wait.SetIgnoringObjectDisposed(); }); SendRequest(request); @@ -1140,12 +1137,12 @@ public SftpFileAttributes RequestFStat(byte[] handle, bool nullOnError) response => { attributes = response.Attributes; - _ = wait.Set(); + wait.SetIgnoringObjectDisposed(); }, response => { exception = GetSftpException(response); - _ = wait.Set(); + wait.SetIgnoringObjectDisposed(); }); SendRequest(request); @@ -1207,7 +1204,7 @@ public void RequestSetStat(string path, SftpFileAttributes attributes) response => { exception = GetSftpException(response); - _ = wait.Set(); + wait.SetIgnoringObjectDisposed(); }); SendRequest(request); @@ -1239,7 +1236,7 @@ public void RequestFSetStat(byte[] handle, SftpFileAttributes attributes) response => { exception = GetSftpException(response); - _ = wait.Set(); + wait.SetIgnoringObjectDisposed(); }); SendRequest(request); @@ -1274,12 +1271,12 @@ public byte[] RequestOpenDir(string path, bool nullOnError = false) response => { handle = response.Handle; - _ = wait.Set(); + wait.SetIgnoringObjectDisposed(); }, response => { exception = GetSftpException(response); - _ = wait.Set(); + wait.SetIgnoringObjectDisposed(); }); SendRequest(request); @@ -1345,7 +1342,7 @@ public KeyValuePair[] RequestReadDir(byte[] handle) response => { result = response.Files; - _ = wait.Set(); + wait.SetIgnoringObjectDisposed(); }, response => { @@ -1354,7 +1351,7 @@ public KeyValuePair[] RequestReadDir(byte[] handle) exception = GetSftpException(response); } - _ = wait.Set(); + wait.SetIgnoringObjectDisposed(); }); SendRequest(request); @@ -1426,7 +1423,7 @@ public void RequestRemove(string path) response => { exception = GetSftpException(response); - _ = wait.Set(); + wait.SetIgnoringObjectDisposed(); }); SendRequest(request); @@ -1493,7 +1490,7 @@ public void RequestMkDir(string path) response => { exception = GetSftpException(response); - _ = wait.Set(); + wait.SetIgnoringObjectDisposed(); }); SendRequest(request); @@ -1558,7 +1555,7 @@ public void RequestRmDir(string path) response => { exception = GetSftpException(response); - _ = wait.Set(); + wait.SetIgnoringObjectDisposed(); }); SendRequest(request); @@ -1625,12 +1622,12 @@ internal KeyValuePair[] RequestRealPath(string path, response => { result = response.Files; - _ = wait.Set(); + wait.SetIgnoringObjectDisposed(); }, response => { exception = GetSftpException(response); - _ = wait.Set(); + wait.SetIgnoringObjectDisposed(); }); SendRequest(request); @@ -1751,12 +1748,12 @@ public SftpFileAttributes RequestStat(string path, bool nullOnError = false) response => { attributes = response.Attributes; - _ = wait.Set(); + wait.SetIgnoringObjectDisposed(); }, response => { exception = GetSftpException(response); - _ = wait.Set(); + wait.SetIgnoringObjectDisposed(); }); SendRequest(request); @@ -1849,7 +1846,7 @@ public void RequestRename(string oldPath, string newPath) response => { exception = GetSftpException(response); - _ = wait.Set(); + wait.SetIgnoringObjectDisposed(); }); SendRequest(request); @@ -1930,12 +1927,12 @@ internal KeyValuePair[] RequestReadLink(string path, response => { result = response.Files; - _ = wait.Set(); + wait.SetIgnoringObjectDisposed(); }, response => { exception = GetSftpException(response); - _ = wait.Set(); + wait.SetIgnoringObjectDisposed(); }); SendRequest(request); @@ -1975,7 +1972,7 @@ public void RequestSymLink(string linkpath, string targetpath) response => { exception = GetSftpException(response); - _ = wait.Set(); + wait.SetIgnoringObjectDisposed(); }); SendRequest(request); @@ -2013,7 +2010,7 @@ public void RequestPosixRename(string oldPath, string newPath) response => { exception = GetSftpException(response); - _ = wait.Set(); + wait.SetIgnoringObjectDisposed(); }); if (!_supportedExtensions.ContainsKey(request.Name)) @@ -2060,12 +2057,12 @@ public SftpFileSystemInformation RequestStatVfs(string path, bool nullOnError = response => { information = response.GetReply().Information; - _ = wait.Set(); + wait.SetIgnoringObjectDisposed(); }, response => { exception = GetSftpException(response); - _ = wait.Set(); + wait.SetIgnoringObjectDisposed(); }); if (!_supportedExtensions.ContainsKey(request.Name)) @@ -2148,12 +2145,12 @@ internal SftpFileSystemInformation RequestFStatVfs(byte[] handle, bool nullOnErr response => { information = response.GetReply().Information; - _ = wait.Set(); + wait.SetIgnoringObjectDisposed(); }, response => { exception = GetSftpException(response); - _ = wait.Set(); + wait.SetIgnoringObjectDisposed(); }); if (!_supportedExtensions.ContainsKey(request.Name)) @@ -2197,7 +2194,7 @@ internal void HardLink(string oldPath, string newPath) response => { exception = GetSftpException(response); - _ = wait.Set(); + wait.SetIgnoringObjectDisposed(); }); if (!_supportedExtensions.ContainsKey(request.Name))