未验证 提交 c112de11 编写于 作者: A Ahmet İbrahim AKSOY 提交者: GitHub

[Unix]: AcceptAsync with existing AcceptSocket support on Unix (#73499)

* Fix: Initial attempt to fix - ut passed

* Update: Forgotten save

* Update: Clear and Dispose ops on handles

* Update: Activate tests for Unix and correct no reuse behavior

* Update: Review Changes

* Update: Deleted forgotten comment

* Update: Review change
上级 2ac87a95
......@@ -53,6 +53,8 @@ public SafeSocketHandle(IntPtr preexistingHandle, bool ownsHandle)
internal bool OwnsHandle { get; }
internal bool HasShutdownSend => _hasShutdownSend;
private bool TryOwnClose()
=> Interlocked.CompareExchange(ref _ownClose, 1, 0) == 0;
......
......@@ -6,6 +6,8 @@
using System.Threading.Tasks;
using System.Runtime.Versioning;
using Microsoft.Win32.SafeHandles;
using System.Reflection;
using System.Collections;
namespace System.Net.Sockets
{
......@@ -166,16 +168,20 @@ private static void ThrowMultiConnectNotSupported()
}
#pragma warning disable CA1822
private Socket? GetOrCreateAcceptSocket(Socket? acceptSocket, bool unused, string propertyName, out SafeSocketHandle? handle)
private Socket? GetOrCreateAcceptSocket(Socket? acceptSocket, bool checkDisconnected, string propertyName, out SafeSocketHandle? handle)
{
// AcceptSocket is not supported on Unix.
if (acceptSocket != null)
if (acceptSocket != null && acceptSocket._handle.HasShutdownSend)
{
throw new PlatformNotSupportedException(SR.PlatformNotSupported_AcceptSocket);
throw new SocketException((int)SocketError.InvalidArgument);
}
if (acceptSocket != null && acceptSocket._rightEndPoint != null && (!checkDisconnected || !acceptSocket._isDisconnected))
{
throw new InvalidOperationException(SR.Format(SR.net_sockets_namedmustnotbebound, propertyName));
}
handle = null;
return null;
return acceptSocket;
}
#pragma warning restore CA1822
......@@ -228,5 +234,81 @@ private void SendFileInternal(string? fileName, ReadOnlySpan<byte> preBuffer, Re
Send(postBuffer);
}
}
internal void DisposeHandle()
{
_handle.Dispose();
}
internal void ClearHandle()
{
_handle = null!;
}
internal Socket CopyStateFromSource(Socket source)
{
_addressFamily = source._addressFamily;
_closeTimeout = source._closeTimeout;
_disposed = source._disposed;
_handle = source._handle;
_isConnected = source._isConnected;
_isDisconnected = source._isDisconnected;
_isListening = source._isListening;
_nonBlockingConnectInProgress = source._nonBlockingConnectInProgress;
_protocolType = source._protocolType;
_receivingPacketInformation = source._receivingPacketInformation;
_remoteEndPoint = source._remoteEndPoint;
_rightEndPoint = source._rightEndPoint;
_socketType = source._socketType;
_willBlock = source._willBlock;
_willBlockInternal = source._willBlockInternal;
_localEndPoint = source._localEndPoint;
_multiBufferReceiveEventArgs = source._multiBufferReceiveEventArgs;
_multiBufferSendEventArgs = source._multiBufferSendEventArgs;
_pendingConnectRightEndPoint = source._pendingConnectRightEndPoint;
_singleBufferReceiveEventArgs = source._singleBufferReceiveEventArgs;
#if DEBUG
// Try to detect if a property gets added that we're not copying correctly.
foreach (PropertyInfo pi in typeof(Socket).GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly))
{
object? origValue = pi.GetValue(source);
object? cloneValue = pi.GetValue(this);
if (origValue is IEnumerable origEnumerable)
{
IEnumerable? cloneEnumerable = cloneValue as IEnumerable;
Debug.Assert(cloneEnumerable != null, $"{pi.Name}. Expected enumerable cloned value.");
IEnumerator e1 = origEnumerable.GetEnumerator();
try
{
IEnumerator e2 = cloneEnumerable.GetEnumerator();
try
{
while (e1.MoveNext())
{
Debug.Assert(e2.MoveNext(), $"{pi.Name}. Cloned enumerator too short.");
Debug.Assert(Equals(e1.Current, e2.Current), $"{pi.Name}. Cloned enumerator's values don't match.");
}
Debug.Assert(!e2.MoveNext(), $"{pi.Name}. Cloned enumerator too long.");
}
finally
{
(e2 as IDisposable)?.Dispose();
}
}
finally
{
(e1 as IDisposable)?.Dispose();
}
}
else
{
Debug.Assert(Equals(origValue, cloneValue), $"{pi.Name}. Expected: {origValue}, Actual: {cloneValue}");
}
}
#endif
return this;
}
}
}
......@@ -335,9 +335,21 @@ internal void LogBuffer(int size)
private SocketError FinishOperationAccept(Internals.SocketAddress remoteSocketAddress)
{
System.Buffer.BlockCopy(_acceptBuffer!, 0, remoteSocketAddress.Buffer, 0, _acceptAddressBufferCount);
Socket? sukru = _acceptSocket;
_acceptSocket = _currentSocket!.CreateAcceptSocket(
SocketPal.CreateSocket(_acceptedFileDescriptor),
_currentSocket._rightEndPoint!.Create(remoteSocketAddress));
if (sukru != null)
{
sukru.DisposeHandle();
sukru.CopyStateFromSource(_acceptSocket);
// We keep this socket to make clean-up.
Socket temp = _acceptSocket;
_acceptSocket = sukru;
temp.ClearHandle();
temp.Dispose();
GC.SuppressFinalize(temp);
}
return SocketError.Success;
}
......
......@@ -145,7 +145,6 @@ public async Task Accept_ConcurrentAcceptsAfterConnects_Success(int numberAccept
[OuterLoop]
[Fact]
[ActiveIssue("https://github.com/dotnet/runtime/issues/1483", TestPlatforms.AnyUnix)]
public async Task Accept_WithTargetSocket_Success()
{
if (!SupportsAcceptIntoExistingSocket)
......@@ -167,7 +166,6 @@ public async Task Accept_WithTargetSocket_Success()
}
}
[ActiveIssue("https://github.com/dotnet/runtime/issues/1483", TestPlatforms.AnyUnix)]
[OuterLoop]
[Theory]
[InlineData(false)]
......@@ -222,7 +220,6 @@ public async Task Accept_WithTargetSocket_ReuseAfterDisconnect_Success(bool reus
[OuterLoop]
[Fact]
[ActiveIssue("https://github.com/dotnet/runtime/issues/1483", TestPlatforms.AnyUnix)]
public async Task Accept_WithAlreadyBoundTargetSocket_Fails()
{
if (!SupportsAcceptIntoExistingSocket)
......@@ -243,7 +240,6 @@ public async Task Accept_WithAlreadyBoundTargetSocket_Fails()
[OuterLoop]
[Fact]
[ActiveIssue("https://github.com/dotnet/runtime/issues/1483", TestPlatforms.AnyUnix)]
public async Task Accept_WithInUseTargetSocket_Fails()
{
if (!SupportsAcceptIntoExistingSocket)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册