diff --git a/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Unix.cs b/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Unix.cs index ec5d17cd504dd8a8d47211883030cb9dc5885f3c..2f93a77b4ecc03a8b2bb18dbe5d3f81198ef8409 100644 --- a/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Unix.cs +++ b/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Unix.cs @@ -8,6 +8,7 @@ using Microsoft.Win32.SafeHandles; using System.Reflection; using System.Collections; +using System.Threading; namespace System.Net.Sockets { @@ -108,7 +109,7 @@ internal void ReplaceHandleIfNecessaryAfterFailedConnect() SocketError errorCode = ReplaceHandle(); if (errorCode != SocketError.Success) { - throw new SocketException((int) errorCode); + throw new SocketException((int)errorCode); } _handle.LastConnectFailed = false; @@ -137,14 +138,22 @@ internal SocketError ReplaceHandle() // Then replace the handle with a new one SafeSocketHandle oldHandle = _handle; - SocketError errorCode = SocketPal.CreateSocket(_addressFamily, _socketType, _protocolType, out _handle); + SocketError errorCode = SocketPal.CreateSocket(_addressFamily, _socketType, _protocolType, out SafeSocketHandle newHandle); + Volatile.Write(ref _handle, newHandle); oldHandle.TransferTrackedState(_handle); oldHandle.Dispose(); + if (errorCode != SocketError.Success) { return errorCode; } + if (Volatile.Read(ref _disposed) != 0) + { + _handle.Dispose(); + throw new ObjectDisposedException(GetType().FullName); + } + // And put back the copied settings. For DualMode, we use the value stored in the _handle // rather than querying the socket itself, as on Unix stacks binding a dual-mode socket to // an IPv6 address may cause the IPv6Only setting to revert to true.