From b25aabc4165493c34b116b8808b7aa29595048a6 Mon Sep 17 00:00:00 2001 From: dudu Date: Sat, 23 Nov 2024 12:42:52 +0800 Subject: [PATCH] refactor: deal with socket disposed exception --- src/Enyim.Caching/Memcached/MemcachedNode.cs | 82 ++++++++++++-------- src/Enyim.Caching/Memcached/PooledSocket.cs | 46 +++++++---- 2 files changed, 82 insertions(+), 46 deletions(-) diff --git a/src/Enyim.Caching/Memcached/MemcachedNode.cs b/src/Enyim.Caching/Memcached/MemcachedNode.cs index 23a30bfc..30029f9f 100755 --- a/src/Enyim.Caching/Memcached/MemcachedNode.cs +++ b/src/Enyim.Caching/Memcached/MemcachedNode.cs @@ -1,8 +1,6 @@ using Enyim.Caching.Configuration; -using Enyim.Caching.Memcached.Protocol.Binary; using Enyim.Caching.Memcached.Results; using Enyim.Caching.Memcached.Results.Extensions; -using Enyim.Collections; using Microsoft.Extensions.Logging; using System; using System.Collections.Concurrent; @@ -12,8 +10,6 @@ using System.Net; using System.Net.Security; using System.Net.Sockets; -using System.Runtime.Serialization; -using System.Security; using System.Threading; using System.Threading.Tasks; @@ -899,49 +895,71 @@ protected internal virtual PooledSocket CreateSocket() { try { - var ps = new PooledSocket(_endPoint, _config.ConnectionTimeout, _config.ReceiveTimeout, _logger, -#if NET5_0_OR_GREATER - _useSslStream, _useIPv6, _sslClientAuthOptions); -#else - _useSslStream, _useIPv6); -#endif - ps.Connect(); - return ps; + return CreateSocketInternal(); } - catch (Exception ex) + catch { - _logger.LogError(ex, $"Create {nameof(PooledSocket)}"); - throw; + try + { + return CreateSocketInternal(); + } + catch (Exception ex) + { + LogCreateSocketError(ex, nameof(CreateSocket)); + throw; + } } } - protected internal virtual async Task CreateSocketAsync() + private PooledSocket CreateSocketInternal() { - try - { - var ps = new PooledSocket(_endPoint, _config.ConnectionTimeout, _config.ReceiveTimeout, _logger, + var ps = new PooledSocket(_endPoint, _config.ConnectionTimeout, _config.ReceiveTimeout, _logger, #if NET5_0_OR_GREATER - _useSslStream, _useIPv6, _sslClientAuthOptions); + _useSslStream, _useIPv6, _sslClientAuthOptions); #else - _useSslStream, _useIPv6); + _useSslStream, _useIPv6); #endif - await ps.ConnectAsync(); - return ps; + ps.Connect(); + return ps; + } + + protected internal virtual async Task CreateSocketAsync() + { + try + { + return await CreateSocketInternalAsync(); } - catch (Exception ex) + catch { - var endPointStr = _endPoint.ToString().Replace("Unspecified/", string.Empty); - _logger.LogError(ex, $"Failed to {nameof(CreateSocketAsync)} to {endPointStr}"); - throw; + try + { + return await CreateSocketInternalAsync(); + } + catch (Exception ex) + { + LogCreateSocketError(ex, nameof(CreateSocketAsync)); + throw; + } } } - //protected internal virtual PooledSocket CreateSocket(IPEndPoint endpoint, TimeSpan connectionTimeout, TimeSpan receiveTimeout) - //{ - // PooledSocket retval = new PooledSocket(endPoint, connectionTimeout, receiveTimeout); + private async Task CreateSocketInternalAsync() + { + var ps = new PooledSocket(_endPoint, _config.ConnectionTimeout, _config.ReceiveTimeout, _logger, +#if NET5_0_OR_GREATER + _useSslStream, _useIPv6, _sslClientAuthOptions); +#else + _useSslStream, _useIPv6); +#endif + await ps.ConnectAsync(); + return ps; + } - // return retval; - //} + private void LogCreateSocketError(Exception ex, string operation) + { + var endPointStr = _endPoint.ToString().Replace("Unspecified/", string.Empty); + _logger.LogError(ex, "Failed to {operation} to {EndPoint}", operation, endPointStr); + } protected virtual IPooledSocketResult ExecuteOperation(IOperation op) { diff --git a/src/Enyim.Caching/Memcached/PooledSocket.cs b/src/Enyim.Caching/Memcached/PooledSocket.cs index 03e8b8d4..a45da1bd 100755 --- a/src/Enyim.Caching/Memcached/PooledSocket.cs +++ b/src/Enyim.Caching/Memcached/PooledSocket.cs @@ -18,9 +18,10 @@ public partial class PooledSocket : IDisposable private readonly ILogger _logger; private bool _isAlive; - private bool _useSslStream; - private bool _useIPv6; + private readonly bool _useSslStream; + private readonly bool _useIPv6; private Socket _socket; + private bool _isSocketDisposed; private readonly EndPoint _endpoint; private readonly int _connectionTimeout; @@ -74,7 +75,7 @@ public PooledSocket(EndPoint endpoint, TimeSpan connectionTimeout, TimeSpan rece _socket = socket; } - public void Connect() + public bool Connect() { bool success = false; @@ -86,8 +87,7 @@ void Cancel() { if (_socket != null && !_socket.Connected) { - _socket.Dispose(); - _socket = null; + DisposeSocket(); } } @@ -95,11 +95,13 @@ void Cancel() try { + if (_isSocketDisposed) return false; _socket.Connect(_endpoint); } catch (PlatformNotSupportedException) { var ep = GetIPEndPoint(_endpoint); + if (_isSocketDisposed) return false; _socket.Connect(ep.Address, ep.Port); } @@ -111,8 +113,7 @@ void Cancel() } else { - _socket.Dispose(); - _socket = null; + DisposeSocket(); } } @@ -133,6 +134,8 @@ void Cancel() { _inputStream = new NetworkStream(_socket); } + + return true; } else { @@ -140,10 +143,15 @@ void Cancel() } } - public async Task ConnectAsync() + public async Task ConnectAsync() { bool success = false; + if (_isSocketDisposed) + { + return false; + } + try { var connTask = _socket.ConnectAsync(_endpoint); @@ -156,8 +164,7 @@ public async Task ConnectAsync() { if (_socket != null) { - _socket.Dispose(); - _socket = null; + DisposeSocket(); } throw new TimeoutException($"Timeout to connect to {_endpoint}."); @@ -166,6 +173,7 @@ public async Task ConnectAsync() catch (PlatformNotSupportedException) { var ep = GetIPEndPoint(_endpoint); + if (_isSocketDisposed) return false; await _socket.ConnectAsync(ep.Address, ep.Port); } @@ -177,8 +185,7 @@ public async Task ConnectAsync() } else { - _socket.Dispose(); - _socket = null; + DisposeSocket(); } } @@ -199,6 +206,8 @@ await _sslStream.AuthenticateAsClientAsync( { _inputStream = new NetworkStream(_socket); } + + return true; } else { @@ -333,7 +342,7 @@ protected void Dispose(bool disposing) } catch (Exception e) { - _logger.LogError(nameof(PooledSocket), e); + _logger.LogError(e, nameof(PooledSocket)); } } else @@ -352,8 +361,17 @@ void IDisposable.Dispose() private void CheckDisposed() { - if (_socket == null) + if (_isSocketDisposed || _socket == null) + { throw new ObjectDisposedException("PooledSocket"); + } + } + + private void DisposeSocket() + { + _isSocketDisposed = true; + _socket.Dispose(); + _socket = null; } ///