From 82327bb36f55a20b6113397c15b91660e499ef5b Mon Sep 17 00:00:00 2001 From: Tomas Weinfurt Date: Sat, 20 May 2023 14:58:12 -0700 Subject: [PATCH] avoid GCHandle in ConnectEx and SendTo on Windows (#86524) * avoid GCHandle in ConnectEx and SendTo on Windows * s/Span/ReadOnlySpan/ndd --- .../src/Interop/Windows/WinSock/Interop.WSASendTo.cs | 12 +++++------- .../src/System/Net/Sockets/DynamicWinsockMethods.cs | 8 ++++---- .../src/System/Net/Sockets/Socket.Windows.cs | 5 ++--- .../src/System/Net/Sockets/SocketAsyncEventArgs.Windows.cs | 14 +++----------- 4 files changed, 14 insertions(+), 25 deletions(-) diff --git a/src/libraries/Common/src/Interop/Windows/WinSock/Interop.WSASendTo.cs b/src/libraries/Common/src/Interop/Windows/WinSock/Interop.WSASendTo.cs index 997af04..1f77c3a 100644 --- a/src/libraries/Common/src/Interop/Windows/WinSock/Interop.WSASendTo.cs +++ b/src/libraries/Common/src/Interop/Windows/WinSock/Interop.WSASendTo.cs @@ -18,7 +18,7 @@ internal static partial class Interop int bufferCount, out int bytesTransferred, SocketFlags socketFlags, - IntPtr socketAddress, + ReadOnlySpan socketAddress, int socketAddressSize, NativeOverlapped* overlapped, IntPtr completionRoutine); @@ -29,8 +29,7 @@ internal static partial class Interop int bufferCount, out int bytesTransferred, SocketFlags socketFlags, - IntPtr socketAddress, - int socketAddressSize, + ReadOnlySpan socketAddress, NativeOverlapped* overlapped, IntPtr completionRoutine) { @@ -38,7 +37,7 @@ internal static partial class Interop // We don't want to cause a race in async scenarios. // The WSABuffer struct should be unchanged anyway. WSABuffer localBuffer = buffer; - return WSASendTo(socketHandle, &localBuffer, bufferCount, out bytesTransferred, socketFlags, socketAddress, socketAddressSize, overlapped, completionRoutine); + return WSASendTo(socketHandle, &localBuffer, bufferCount, out bytesTransferred, socketFlags, socketAddress, socketAddress.Length, overlapped, completionRoutine); } internal static unsafe SocketError WSASendTo( @@ -47,15 +46,14 @@ internal static partial class Interop int bufferCount, [Out] out int bytesTransferred, SocketFlags socketFlags, - IntPtr socketAddress, - int socketAddressSize, + ReadOnlySpan socketAddress, NativeOverlapped* overlapped, IntPtr completionRoutine) { Debug.Assert(buffers != null && buffers.Length > 0); fixed (WSABuffer* buffersPtr = &buffers[0]) { - return WSASendTo(socketHandle, buffersPtr, bufferCount, out bytesTransferred, socketFlags, socketAddress, socketAddressSize, overlapped, completionRoutine); + return WSASendTo(socketHandle, buffersPtr, bufferCount, out bytesTransferred, socketFlags, socketAddress, socketAddress.Length, overlapped, completionRoutine); } } } diff --git a/src/libraries/System.Net.Sockets/src/System/Net/Sockets/DynamicWinsockMethods.cs b/src/libraries/System.Net.Sockets/src/System/Net/Sockets/DynamicWinsockMethods.cs index a3abe36..3ade534 100644 --- a/src/libraries/System.Net.Sockets/src/System/Net/Sockets/DynamicWinsockMethods.cs +++ b/src/libraries/System.Net.Sockets/src/System/Net/Sockets/DynamicWinsockMethods.cs @@ -174,7 +174,7 @@ namespace System.Net.Sockets Marshal.SetLastPInvokeError(Marshal.GetLastSystemError()); } - internal unsafe bool ConnectEx(SafeSocketHandle socketHandle, IntPtr socketAddress, int socketAddressSize, IntPtr buffer, int dataLength, out int bytesSent, NativeOverlapped* overlapped) + internal unsafe bool ConnectEx(SafeSocketHandle socketHandle, ReadOnlySpan socketAddress, IntPtr buffer, int dataLength, out int bytesSent, NativeOverlapped* overlapped) { IntPtr __socketHandle_gen_native = default; bytesSent = default; @@ -192,8 +192,9 @@ namespace System.Net.Sockets socketHandle.DangerousAddRef(ref socketHandle__addRefd); __socketHandle_gen_native = socketHandle.DangerousGetHandle(); fixed (int* __bytesSent_gen_native = &bytesSent) + fixed (void* socketAddressPtr = &MemoryMarshal.GetReference(socketAddress)) { - __retVal_gen_native = ((delegate* unmanaged)_target)(__socketHandle_gen_native, socketAddress, socketAddressSize, buffer, dataLength, __bytesSent_gen_native, overlapped); + __retVal_gen_native = ((delegate* unmanaged)_target)(__socketHandle_gen_native, socketAddressPtr, socketAddress.Length, buffer, dataLength, __bytesSent_gen_native, overlapped); } Marshal.SetLastPInvokeError(Marshal.GetLastSystemError()); // @@ -338,8 +339,7 @@ namespace System.Net.Sockets internal unsafe delegate bool ConnectExDelegate( SafeSocketHandle socketHandle, - IntPtr socketAddress, - int socketAddressSize, + ReadOnlySpan socketAddress, IntPtr buffer, int dataLength, out int bytesSent, diff --git a/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Windows.cs b/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Windows.cs index 11a5607..c7467ee 100644 --- a/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Windows.cs +++ b/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Windows.cs @@ -266,8 +266,7 @@ namespace System.Net.Sockets } internal unsafe bool ConnectEx(SafeSocketHandle socketHandle, - IntPtr socketAddress, - int socketAddressSize, + ReadOnlySpan socketAddress, IntPtr buffer, int dataLength, out int bytesSent, @@ -275,7 +274,7 @@ namespace System.Net.Sockets { ConnectExDelegate connectEx = GetDynamicWinsockMethods().GetConnectExDelegate(socketHandle); - return connectEx(socketHandle, socketAddress, socketAddressSize, buffer, dataLength, out bytesSent, overlapped); + return connectEx(socketHandle, socketAddress, buffer, dataLength, out bytesSent, overlapped); } internal unsafe SocketError WSARecvMsg(SafeSocketHandle socketHandle, IntPtr msg, out int bytesTransferred, NativeOverlapped* overlapped, IntPtr completionRoutine) diff --git a/src/libraries/System.Net.Sockets/src/System/Net/Sockets/SocketAsyncEventArgs.Windows.cs b/src/libraries/System.Net.Sockets/src/System/Net/Sockets/SocketAsyncEventArgs.Windows.cs index 9a6c84a..004b8da 100644 --- a/src/libraries/System.Net.Sockets/src/System/Net/Sockets/SocketAsyncEventArgs.Windows.cs +++ b/src/libraries/System.Net.Sockets/src/System/Net/Sockets/SocketAsyncEventArgs.Windows.cs @@ -295,8 +295,6 @@ namespace System.Net.Sockets // ConnectEx uses a sockaddr buffer containing the remote address to which to connect. // It can also optionally take a single buffer of data to send after the connection is complete. - // The sockaddr is pinned with a GCHandle to avoid having to use the object array form of UnsafePack. - PinSocketAddressBuffer(); fixed (byte* bufferPtr = &MemoryMarshal.GetReference(_buffer.Span)) { @@ -305,8 +303,7 @@ namespace System.Net.Sockets { bool success = socket.ConnectEx( handle, - PtrSocketAddressBuffer, - _socketAddress!.Size, + _socketAddress!.Buffer.AsSpan(), (IntPtr)(bufferPtr + _offset), _count, out int bytesTransferred, @@ -743,9 +740,6 @@ namespace System.Net.Sockets // receive data and from which to send data respectively. Single and multiple buffers // are handled differently so as to optimize performance for the more common single buffer case. // - // WSARecvFrom and WSASendTo also uses a sockaddr buffer in which to store the address from which the data was received. - // The sockaddr is pinned with a GCHandle to avoid having to use the object array form of UnsafePack. - PinSocketAddressBuffer(); return _bufferList == null ? DoOperationSendToSingleBuffer(handle, cancellationToken) : @@ -769,8 +763,7 @@ namespace System.Net.Sockets 1, out int bytesTransferred, _socketFlags, - PtrSocketAddressBuffer, - _socketAddress!.Size, + _socketAddress!.Buffer.AsSpan(), overlapped, IntPtr.Zero); @@ -797,8 +790,7 @@ namespace System.Net.Sockets _bufferListInternal!.Count, out int bytesTransferred, _socketFlags, - PtrSocketAddressBuffer, - _socketAddress!.Size, + _socketAddress!.Buffer.AsSpan(), overlapped, IntPtr.Zero); -- 2.7.4