From 504d1dc035bd2ea75e7f8dc2456fbcb89975bc00 Mon Sep 17 00:00:00 2001 From: drieseng Date: Sun, 3 May 2020 13:10:30 +0200 Subject: [PATCH] Prefer Socket.Poll(...) over Socket.Select(...). Fixes #355. --- src/Renci.SshNet/Session.cs | 60 ++++++++++++++++++------------------- 1 file changed, 29 insertions(+), 31 deletions(-) diff --git a/src/Renci.SshNet/Session.cs b/src/Renci.SshNet/Session.cs index fd771095..9edcb687 100644 --- a/src/Renci.SshNet/Session.cs +++ b/src/Renci.SshNet/Session.cs @@ -1784,16 +1784,16 @@ namespace Renci.SshNet /// /// #else -/// -/// Gets a value indicating whether the socket is connected. -/// -/// -/// true if the socket is connected; otherwise, false. -/// -/// -/// We verify whether is true. However, this only returns the state -/// of the socket as of the last I/O operation. -/// + /// + /// Gets a value indicating whether the socket is connected. + /// + /// + /// true if the socket is connected; otherwise, false. + /// + /// + /// We verify whether is true. However, this only returns the state + /// of the socket as of the last I/O operation. + /// #endif private bool IsSocketConnected() { @@ -1920,16 +1920,23 @@ namespace Renci.SshNet /// private void MessageListener() { -#if FEATURE_SOCKET_SELECT - var readSockets = new List { _socket }; -#endif // FEATURE_SOCKET_SELECT - try { // remain in message loop until socket is shut down or until we're disconnecting while (_socket.IsConnected()) { -#if FEATURE_SOCKET_SELECT +#if FEATURE_SOCKET_POLL + // Block until either data is available or the socket is closed + var connectionClosedOrDataAvailable = _socket.Poll(-1, SelectMode.SelectRead); + if (connectionClosedOrDataAvailable && _socket.Available == 0) + { + // connection with SSH server was closed or socket was disposed; + // break out of the message loop + break; + } +#elif FEATURE_SOCKET_SELECT + var readSockets = new List { _socket }; + // if the socket is already disposed when Select is invoked, then a SocketException // stating "An operation was attempted on something that is not a socket" is thrown; // we attempt to avoid this exception by having an IsConnected() that can break the @@ -1963,18 +1970,9 @@ namespace Renci.SshNet // break out of the message loop break; } -#elif FEATURE_SOCKET_POLL - // when Socket.Select(IList, IList, IList, Int32) is not available or is buggy, we use - // Socket.Poll(Int, SelectMode) to block until either data is available or the socket - // is closed - _socket.Poll(-1, SelectMode.SelectRead); - - if (!_socket.IsConnected()) - { - // connection with SSH server was closed or socket was disposed; - // break out of the message loop - break; - } +#else + #error Blocking wait on either socket data to become available or connection to be + #error closed is not implemented. #endif // FEATURE_SOCKET_SELECT var message = ReceiveMessage(); @@ -2459,7 +2457,7 @@ namespace Renci.SshNet DisconnectReason.ConnectionLost); } - #region IDisposable implementation +#region IDisposable implementation private bool _disposed; @@ -2550,9 +2548,9 @@ namespace Renci.SshNet Dispose(false); } - #endregion IDisposable implementation +#endregion IDisposable implementation - #region ISession implementation +#region ISession implementation /// /// Gets or sets the connection info. @@ -2638,7 +2636,7 @@ namespace Renci.SshNet return TrySendMessage(message); } - #endregion ISession implementation +#endregion ISession implementation } ///