From 8cecca07a2eb65a6d41d38a565bf1b56247b9deb Mon Sep 17 00:00:00 2001 From: BrennanConroy Date: Wed, 31 Jan 2018 15:51:33 -0800 Subject: [PATCH] Fix race in Restart during Close task (#1263) --- .../HttpConnection.cs | 33 +++++++++++++++---- 1 file changed, 27 insertions(+), 6 deletions(-) diff --git a/src/Microsoft.AspNetCore.Sockets.Client.Http/HttpConnection.cs b/src/Microsoft.AspNetCore.Sockets.Client.Http/HttpConnection.cs index 68d6ad8b6f..5a58227945 100644 --- a/src/Microsoft.AspNetCore.Sockets.Client.Http/HttpConnection.cs +++ b/src/Microsoft.AspNetCore.Sockets.Client.Http/HttpConnection.cs @@ -516,24 +516,45 @@ namespace Microsoft.AspNetCore.Sockets.Client // _startTask is returned to the user and they should handle exceptions. } + TaskCompletionSource closeTcs = null; + Task receiveLoopTask = null; + ITransport transport = null; + + lock (_stateChangeLock) + { + // Copy locals in lock to prevent a race when the server closes the connection and StopAsync is called + // at the same time + if (_connectionState != ConnectionState.Connected) + { + // If not Connected then someone else disconnected while StopAsync was in progress, we can now NO-OP + return; + } + + // Create locals of relevant member variables to prevent a race when Closed event triggers a connect + // while StopAsync is still running + closeTcs = _closeTcs; + receiveLoopTask = _receiveLoopTask; + transport = _transport; + } + if (_transportChannel != null) { Output.TryComplete(); } - if (_transport != null) + if (transport != null) { - await _transport.StopAsync(); + await transport.StopAsync(); } - if (_receiveLoopTask != null) + if (receiveLoopTask != null) { - await _receiveLoopTask; + await receiveLoopTask; } - if (_closeTcs != null) + if (closeTcs != null) { - await _closeTcs.Task; + await closeTcs.Task; } }