From da6efb9e04ebefc6a736aee17d7e32f402639afe Mon Sep 17 00:00:00 2001 From: Hao Kung Date: Tue, 19 Apr 2022 13:26:01 -0700 Subject: [PATCH 1/3] Improve abort handling --- src/Servers/IIS/IIS/src/Core/IISHttpContext.IO.cs | 5 +++++ src/Servers/IIS/IIS/src/Core/OutputProducer.cs | 13 ++++++++----- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/src/Servers/IIS/IIS/src/Core/IISHttpContext.IO.cs b/src/Servers/IIS/IIS/src/Core/IISHttpContext.IO.cs index 79ac033f6531..ecdf64c1b49e 100644 --- a/src/Servers/IIS/IIS/src/Core/IISHttpContext.IO.cs +++ b/src/Servers/IIS/IIS/src/Core/IISHttpContext.IO.cs @@ -159,6 +159,11 @@ private async Task WriteBody(bool flush = false) { while (true) { + if (_bodyOutput.Aborted) + { + break; + } + var result = await _bodyOutput.Reader.ReadAsync(); var buffer = result.Buffer; diff --git a/src/Servers/IIS/IIS/src/Core/OutputProducer.cs b/src/Servers/IIS/IIS/src/Core/OutputProducer.cs index 00934ea1b623..3c4b034d4488 100644 --- a/src/Servers/IIS/IIS/src/Core/OutputProducer.cs +++ b/src/Servers/IIS/IIS/src/Core/OutputProducer.cs @@ -9,9 +9,10 @@ namespace Microsoft.AspNetCore.Server.IIS.Core; internal class OutputProducer { - // This locks access to _completed. + // This locks access to _completed and _aborted. private readonly object _contextLock = new object(); private bool _completed; + private bool _aborted; private readonly Pipe _pipe; @@ -29,6 +30,8 @@ public OutputProducer(Pipe pipe) public PipeReader Reader => _pipe.Reader; + public bool Aborted => _aborted; + public Task FlushAsync(CancellationToken cancellationToken) { _pipe.Reader.CancelPendingRead(); @@ -40,7 +43,7 @@ public void Complete() { lock (_contextLock) { - if (_completed) + if (_completed || _aborted) { return; } @@ -54,12 +57,12 @@ public void Abort() { lock (_contextLock) { - if (_completed) + if (_completed || _aborted) { return; } - _completed = true; + _aborted = true; _pipe.Reader.CancelPendingRead(); _pipe.Writer.Complete(); @@ -70,7 +73,7 @@ public Task WriteAsync(ReadOnlyMemory buffer, CancellationToken cancellati { lock (_contextLock) { - if (_completed) + if (_completed || _aborted) { return Task.CompletedTask; } From 62c8bb435f1a77dff9a4758e0c876fd0cf0c081d Mon Sep 17 00:00:00 2001 From: Hao Kung Date: Tue, 19 Apr 2022 13:51:05 -0700 Subject: [PATCH 2/3] PR feedback --- src/Servers/IIS/IIS/src/Core/IISHttpContext.IO.cs | 4 ++-- src/Servers/IIS/IIS/src/Core/OutputProducer.cs | 2 +- src/Servers/IIS/IIS/test/IIS.Tests/ResponseAbortTests.cs | 1 - 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/Servers/IIS/IIS/src/Core/IISHttpContext.IO.cs b/src/Servers/IIS/IIS/src/Core/IISHttpContext.IO.cs index ecdf64c1b49e..1bc77f2d259b 100644 --- a/src/Servers/IIS/IIS/src/Core/IISHttpContext.IO.cs +++ b/src/Servers/IIS/IIS/src/Core/IISHttpContext.IO.cs @@ -159,13 +159,13 @@ private async Task WriteBody(bool flush = false) { while (true) { + var result = await _bodyOutput.Reader.ReadAsync(); + if (_bodyOutput.Aborted) { break; } - var result = await _bodyOutput.Reader.ReadAsync(); - var buffer = result.Buffer; try { diff --git a/src/Servers/IIS/IIS/src/Core/OutputProducer.cs b/src/Servers/IIS/IIS/src/Core/OutputProducer.cs index 3c4b034d4488..60a189ecd61c 100644 --- a/src/Servers/IIS/IIS/src/Core/OutputProducer.cs +++ b/src/Servers/IIS/IIS/src/Core/OutputProducer.cs @@ -12,7 +12,7 @@ internal class OutputProducer // This locks access to _completed and _aborted. private readonly object _contextLock = new object(); private bool _completed; - private bool _aborted; + private volatile bool _aborted; private readonly Pipe _pipe; diff --git a/src/Servers/IIS/IIS/test/IIS.Tests/ResponseAbortTests.cs b/src/Servers/IIS/IIS/test/IIS.Tests/ResponseAbortTests.cs index f614cdc2a12b..dc03cef8df45 100644 --- a/src/Servers/IIS/IIS/test/IIS.Tests/ResponseAbortTests.cs +++ b/src/Servers/IIS/IIS/test/IIS.Tests/ResponseAbortTests.cs @@ -34,7 +34,6 @@ public async Task ClosesWithoutSendingAnything() } [ConditionalFact] - [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/31404")] public async Task ClosesAfterDataSent() { var bodyReceived = CreateTaskCompletionSource(); From e5f9ed29647c2d49f4b7b0b078e9d4f966040ca5 Mon Sep 17 00:00:00 2001 From: Hao Kung Date: Tue, 19 Apr 2022 16:11:28 -0700 Subject: [PATCH 3/3] Update IISHttpContext.IO.cs --- src/Servers/IIS/IIS/src/Core/IISHttpContext.IO.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Servers/IIS/IIS/src/Core/IISHttpContext.IO.cs b/src/Servers/IIS/IIS/src/Core/IISHttpContext.IO.cs index 1bc77f2d259b..32843c36ab03 100644 --- a/src/Servers/IIS/IIS/src/Core/IISHttpContext.IO.cs +++ b/src/Servers/IIS/IIS/src/Core/IISHttpContext.IO.cs @@ -161,14 +161,14 @@ private async Task WriteBody(bool flush = false) { var result = await _bodyOutput.Reader.ReadAsync(); - if (_bodyOutput.Aborted) - { - break; - } - var buffer = result.Buffer; try { + if (_bodyOutput.Aborted) + { + break; + } + if (!buffer.IsEmpty) { await AsyncIO!.WriteAsync(buffer);