Fix HTTP/2 stream output flow control abort error (#23727)

* Fix stream output flow control abort error

* Clean up

* Clean up

* Add timeouts
This commit is contained in:
James Newton-King 2020-07-08 13:41:23 +12:00 committed by GitHub
parent cc3c1d0e74
commit 3709eda270
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 63 additions and 1 deletions

View File

@ -94,7 +94,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2.FlowControl
if (_currentConnectionLevelAwaitable != null &&
_currentConnectionLevelAwaitable.Version == _currentConnectionLevelAwaitableVersion)
{
_currentConnectionLevelAwaitable.SetResult(null);
_currentConnectionLevelAwaitable.TrySetResult(null);
}
}

View File

@ -1594,6 +1594,68 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await WaitForAllStreamsAsync();
}
[Fact]
public async Task OutputFlowControl_ConnectionAndRequestAborted_NoException()
{
// Ensure the stream window size is bigger than the connection window size
_clientSettings.InitialWindowSize = _clientSettings.InitialWindowSize * 2;
var connectionAbortedTcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously);
var requestAbortedTcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously);
await InitializeConnectionAsync(async context =>
{
// Exceed connection window size
await context.Response.WriteAsync(new string('!', 65536));
await connectionAbortedTcs.Task;
try
{
context.Abort();
requestAbortedTcs.SetResult();
}
catch (Exception ex)
{
requestAbortedTcs.SetException(ex);
}
}).DefaultTimeout();
await StartStreamAsync(1, _browserRequestHeaders, endStream: true).DefaultTimeout();
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 32,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS),
withStreamId: 1).DefaultTimeout();
await ExpectAsync(Http2FrameType.DATA,
withLength: 16384,
withFlags: (byte)(Http2DataFrameFlags.NONE),
withStreamId: 1).DefaultTimeout();
await ExpectAsync(Http2FrameType.DATA,
withLength: 16384,
withFlags: (byte)(Http2DataFrameFlags.NONE),
withStreamId: 1).DefaultTimeout();
await ExpectAsync(Http2FrameType.DATA,
withLength: 16384,
withFlags: (byte)(Http2DataFrameFlags.NONE),
withStreamId: 1).DefaultTimeout();
await ExpectAsync(Http2FrameType.DATA,
withLength: 16383,
withFlags: (byte)(Http2DataFrameFlags.NONE),
withStreamId: 1).DefaultTimeout();
_connection.HandleReadDataRateTimeout();
connectionAbortedTcs.SetResult();
// Task completing successfully means HttpContext.Abort didn't throw
await requestAbortedTcs.Task.DefaultTimeout();
}
[Fact]
public async Task DATA_Sent_DespiteStreamOutputFlowControl_IfEmptyAndEndsStream()
{