From 50ac454d8d8a1915188b2a4bb3fff3b81bf6c0cf Mon Sep 17 00:00:00 2001 From: Geoff Kizer Date: Thu, 8 Oct 2020 08:59:08 -0700 Subject: [PATCH] fix issue with duplicate completion in MultipleConnectAsync (#43112) Co-authored-by: Geoffrey Kizer --- .../Net/Sockets/MultipleConnectAsync.cs | 28 ++++++++++++------- .../Net/Sockets/SocketAsyncEventArgs.cs | 11 ++++++-- 2 files changed, 27 insertions(+), 12 deletions(-) diff --git a/src/libraries/System.Net.Sockets/src/System/Net/Sockets/MultipleConnectAsync.cs b/src/libraries/System.Net.Sockets/src/System/Net/Sockets/MultipleConnectAsync.cs index 33a54eb950a..ff10fb26745 100644 --- a/src/libraries/System.Net.Sockets/src/System/Net/Sockets/MultipleConnectAsync.cs +++ b/src/libraries/System.Net.Sockets/src/System/Net/Sockets/MultipleConnectAsync.cs @@ -151,7 +151,7 @@ private bool DoDnsCallback(IAsyncResult result, bool sync) } else if (!pending) { - return DoConnectCallback(_internalArgs!); + return DoConnectCallback(_internalArgs!, sync); } else { @@ -161,13 +161,13 @@ private bool DoDnsCallback(IAsyncResult result, bool sync) private void InternalConnectCallback(object? sender, SocketAsyncEventArgs args) { - DoConnectCallback(args); + DoConnectCallback(args, false); } // Callback which fires when an internal connection attempt completes. // If it failed and there are more addresses to try, do it. // Returns true if the operation is pending, false if it completed synchronously. - private bool DoConnectCallback(SocketAsyncEventArgs args) + private bool DoConnectCallback(SocketAsyncEventArgs args, bool sync) { Exception? exception = null; @@ -243,16 +243,14 @@ private bool DoConnectCallback(SocketAsyncEventArgs args) } } - if (exception == null) + if (exception != null) { - Succeed(); + return Fail(sync, exception); } else { - AsyncFail(exception); + return Succeed(sync); } - - return false; } // Called to initiate a connection attempt to the next address in the list. @@ -287,11 +285,21 @@ private bool DoConnectCallback(SocketAsyncEventArgs args) protected abstract void OnSucceed(); - private void Succeed() + private bool Succeed(bool sync) { OnSucceed(); - _userArgs!.FinishWrapperConnectSuccess(_internalArgs!.ConnectSocket, _internalArgs.BytesTransferred, _internalArgs.SocketFlags); + + if (sync) + { + _userArgs!.FinishWrapperConnectSyncSuccess(_internalArgs!.ConnectSocket, _internalArgs.BytesTransferred, _internalArgs.SocketFlags); + } + else + { + _userArgs!.FinishWrapperConnectAsyncSuccess(_internalArgs!.ConnectSocket, _internalArgs.BytesTransferred, _internalArgs.SocketFlags); + } + _internalArgs.Dispose(); + return !sync; } protected abstract void OnFail(bool abortive); diff --git a/src/libraries/System.Net.Sockets/src/System/Net/Sockets/SocketAsyncEventArgs.cs b/src/libraries/System.Net.Sockets/src/System/Net/Sockets/SocketAsyncEventArgs.cs index c6e77b34601..e85bb70d701 100644 --- a/src/libraries/System.Net.Sockets/src/System/Net/Sockets/SocketAsyncEventArgs.cs +++ b/src/libraries/System.Net.Sockets/src/System/Net/Sockets/SocketAsyncEventArgs.cs @@ -676,7 +676,7 @@ internal void FinishConnectByNameAsyncFailure(Exception exception, int bytesTran } } - internal void FinishWrapperConnectSuccess(Socket? connectSocket, int bytesTransferred, SocketFlags flags) + internal void FinishWrapperConnectSyncSuccess(Socket? connectSocket, int bytesTransferred, SocketFlags flags) { SetResults(SocketError.Success, bytesTransferred, flags); _currentSocket = connectSocket; @@ -685,8 +685,15 @@ internal void FinishWrapperConnectSuccess(Socket? connectSocket, int bytesTransf if (SocketsTelemetry.Log.IsEnabled()) LogBytesTransferEvents(connectSocket?.SocketType, SocketAsyncOperation.Connect, bytesTransferred); // Complete the operation and raise the event. - ExecutionContext? context = _context; // store context before it's cleared as part of completing the operation Complete(); + } + + internal void FinishWrapperConnectAsyncSuccess(Socket? connectSocket, int bytesTransferred, SocketFlags flags) + { + ExecutionContext? context = _context; // store context before it's cleared as part of completing the operation + + FinishWrapperConnectSyncSuccess(connectSocket, bytesTransferred, flags); + if (context == null) { OnCompletedInternal(); -- GitLab