From 8dffc68ceae69000a3c31b0ba861f5b9e1728916 Mon Sep 17 00:00:00 2001 From: BrennanConroy Date: Tue, 11 Sep 2018 15:50:00 -0700 Subject: [PATCH] Cancel previous request on close (#2923) (#2942) --- .../Internal/HttpConnectionDispatcher.cs | 20 +++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/src/Microsoft.AspNetCore.Http.Connections/Internal/HttpConnectionDispatcher.cs b/src/Microsoft.AspNetCore.Http.Connections/Internal/HttpConnectionDispatcher.cs index d66c8ae8b3..24e0090986 100644 --- a/src/Microsoft.AspNetCore.Http.Connections/Internal/HttpConnectionDispatcher.cs +++ b/src/Microsoft.AspNetCore.Http.Connections/Internal/HttpConnectionDispatcher.cs @@ -218,8 +218,18 @@ namespace Microsoft.AspNetCore.Http.Connections.Internal // Cancel the previous request connection.Cancellation?.Cancel(); - // Always wait for the previous request to drain - await connection.PreviousPollTask; + try + { + // Wait for the previous request to drain + await connection.PreviousPollTask; + } + catch (OperationCanceledException) + { + // Previous poll canceled due to connection closing, close this poll too + context.Response.ContentType = "text/plain"; + context.Response.StatusCode = StatusCodes.Status204NoContent; + return; + } connection.PreviousPollTask = currentRequestTcs.Task; } @@ -289,6 +299,9 @@ namespace Microsoft.AspNetCore.Http.Connections.Internal // If the status code is a 204 it means the connection is done if (context.Response.StatusCode == StatusCodes.Status204NoContent) { + // Cancel current request to release any waiting poll and let dispose aquire the lock + currentRequestTcs.TrySetCanceled(); + // We should be able to safely dispose because there's no more data being written // We don't need to wait for close here since we've already waited for both sides await _manager.DisposeAndRemoveAsync(connection, closeGracefully: false); @@ -299,6 +312,9 @@ namespace Microsoft.AspNetCore.Http.Connections.Internal } else if (resultTask.IsFaulted) { + // Cancel current request to release any waiting poll and let dispose aquire the lock + currentRequestTcs.TrySetCanceled(); + // transport task was faulted, we should remove the connection await _manager.DisposeAndRemoveAsync(connection, closeGracefully: false);