From d78e7ea80d734b6d0b094245e8c7727d670e13da Mon Sep 17 00:00:00 2001 From: Stephen Halter Date: Thu, 15 Feb 2018 14:05:45 -0800 Subject: [PATCH] Fixed race in sockets transport (#2279) (#2322) --- .../Internal/SocketConnection.cs | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/Kestrel.Transport.Sockets/Internal/SocketConnection.cs b/src/Kestrel.Transport.Sockets/Internal/SocketConnection.cs index cf128c05f3..2ab964e894 100644 --- a/src/Kestrel.Transport.Sockets/Internal/SocketConnection.cs +++ b/src/Kestrel.Transport.Sockets/Internal/SocketConnection.cs @@ -57,13 +57,14 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.Internal public async Task StartAsync(IConnectionHandler connectionHandler) { + Exception sendError = null; try { connectionHandler.OnConnection(this); // Spawn send and receive logic Task receiveTask = DoReceive(); - Task sendTask = DoSend(); + Task sendTask = DoSend(); // If the sending task completes then close the receive // We don't need to do this in the other direction because the kestrel @@ -76,7 +77,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.Internal // Now wait for both to complete await receiveTask; - await sendTask; + sendError = await sendTask; // Dispose the socket(should noop if already called) _socket.Dispose(); @@ -85,6 +86,11 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.Internal { _trace.LogError(0, ex, $"Unexpected exception in {nameof(SocketConnection)}.{nameof(StartAsync)}."); } + finally + { + // Complete the output after disposing the socket + Output.Complete(sendError); + } } private async Task DoReceive() @@ -181,7 +187,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.Internal } } - private async Task DoSend() + private async Task DoSend() { Exception error = null; @@ -233,8 +239,6 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.Internal } finally { - Output.Complete(error); - // Make sure to close the connection only after the _aborted flag is set. // Without this, the RequestsCanBeAbortedMidRead test will sometimes fail when // a BadHttpRequestException is thrown instead of a TaskCanceledException. @@ -242,6 +246,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.Internal _trace.ConnectionWriteFin(ConnectionId); _socket.Shutdown(SocketShutdown.Both); } + + return error; } } }