Replace ManualResetEvents with a TCS (#6173)

* Added TaskCreationOptions.RunContinuationsAsynchronously in a few places
This commit is contained in:
David Fowler 2018-12-29 08:24:57 -04:00 committed by GitHub
parent dd912850eb
commit b12c33dbc3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 40 additions and 33 deletions

View File

@ -1,4 +1,4 @@
// Copyright (c) .NET Foundation. All rights reserved. // Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System; using System;
@ -21,6 +21,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
public void OnConnectionCreatesLogScopeWithConnectionId() public void OnConnectionCreatesLogScopeWithConnectionId()
{ {
var serviceContext = new TestServiceContext(); var serviceContext = new TestServiceContext();
// This needs to run inline
var tcs = new TaskCompletionSource<object>(); var tcs = new TaskCompletionSource<object>();
var dispatcher = new ConnectionDispatcher(serviceContext, _ => tcs.Task); var dispatcher = new ConnectionDispatcher(serviceContext, _ => tcs.Task);

View File

@ -473,23 +473,26 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
[Fact] [Fact]
public async Task DATA_Received_Multiplexed_AppMustNotBlockOtherFrames() public async Task DATA_Received_Multiplexed_AppMustNotBlockOtherFrames()
{ {
var stream1Read = new ManualResetEvent(false); var stream1Read = new TaskCompletionSource<object>(TaskCreationOptions.RunContinuationsAsynchronously);
var stream1ReadFinished = new ManualResetEvent(false); var stream1ReadFinished = new TaskCompletionSource<object>(TaskCreationOptions.RunContinuationsAsynchronously);
var stream3Read = new ManualResetEvent(false); var stream3Read = new TaskCompletionSource<object>(TaskCreationOptions.RunContinuationsAsynchronously);
var stream3ReadFinished = new ManualResetEvent(false); var stream3ReadFinished = new TaskCompletionSource<object>(TaskCreationOptions.RunContinuationsAsynchronously);
await InitializeConnectionAsync(async context => await InitializeConnectionAsync(async context =>
{ {
var data = new byte[10]; var data = new byte[10];
var read = await context.Request.Body.ReadAsync(new byte[10], 0, 10); var read = await context.Request.Body.ReadAsync(new byte[10], 0, 10);
if (context.Features.Get<IHttp2StreamIdFeature>().StreamId == 1) if (context.Features.Get<IHttp2StreamIdFeature>().StreamId == 1)
{ {
stream1Read.Set(); stream1Read.TrySetResult(null);
Assert.True(stream1ReadFinished.WaitOne(TimeSpan.FromSeconds(10)));
await stream1ReadFinished.Task.DefaultTimeout();
} }
else else
{ {
stream3Read.Set(); stream3Read.TrySetResult(null);
Assert.True(stream3ReadFinished.WaitOne(TimeSpan.FromSeconds(10)));
await stream3ReadFinished.Task.DefaultTimeout();
} }
await context.Response.Body.WriteAsync(data, 0, read); await context.Response.Body.WriteAsync(data, 0, read);
}); });
@ -498,12 +501,12 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(3, _browserRequestHeaders, endStream: false); await StartStreamAsync(3, _browserRequestHeaders, endStream: false);
await SendDataAsync(1, _helloBytes, endStream: true); await SendDataAsync(1, _helloBytes, endStream: true);
Assert.True(stream1Read.WaitOne(TimeSpan.FromSeconds(10))); await stream1Read.Task.DefaultTimeout();
await SendDataAsync(3, _helloBytes, endStream: true); await SendDataAsync(3, _helloBytes, endStream: true);
Assert.True(stream3Read.WaitOne(TimeSpan.FromSeconds(10))); await stream3Read.Task.DefaultTimeout();
stream3ReadFinished.Set(); stream3ReadFinished.TrySetResult(null);
await ExpectAsync(Http2FrameType.HEADERS, await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37, withLength: 37,
@ -518,7 +521,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
withFlags: (byte)Http2DataFrameFlags.END_STREAM, withFlags: (byte)Http2DataFrameFlags.END_STREAM,
withStreamId: 3); withStreamId: 3);
stream1ReadFinished.Set(); stream1ReadFinished.TrySetResult(null);
await ExpectAsync(Http2FrameType.HEADERS, await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37, withLength: 37,
@ -1197,33 +1200,36 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
[Fact] [Fact]
public async Task HEADERS_Received_AppCannotBlockOtherFrames() public async Task HEADERS_Received_AppCannotBlockOtherFrames()
{ {
var firstRequestReceived = new ManualResetEvent(false); var firstRequestReceived = new TaskCompletionSource<object>(TaskCreationOptions.RunContinuationsAsynchronously);
var finishFirstRequest = new ManualResetEvent(false); var finishFirstRequest = new TaskCompletionSource<object>(TaskCreationOptions.RunContinuationsAsynchronously);
var secondRequestReceived = new ManualResetEvent(false); var secondRequestReceived = new TaskCompletionSource<object>(TaskCreationOptions.RunContinuationsAsynchronously);
var finishSecondRequest = new ManualResetEvent(false); var finishSecondRequest = new TaskCompletionSource<object>(TaskCreationOptions.RunContinuationsAsynchronously);
await InitializeConnectionAsync(context =>
await InitializeConnectionAsync(async context =>
{ {
if (!firstRequestReceived.WaitOne(0)) if (!firstRequestReceived.Task.IsCompleted)
{ {
firstRequestReceived.Set(); firstRequestReceived.TrySetResult(null);
Assert.True(finishFirstRequest.WaitOne(TimeSpan.FromSeconds(10)));
await finishFirstRequest.Task.DefaultTimeout();
} }
else else
{ {
secondRequestReceived.Set(); secondRequestReceived.TrySetResult(null);
Assert.True(finishSecondRequest.WaitOne(TimeSpan.FromSeconds(10)));
}
return Task.CompletedTask; await finishSecondRequest.Task.DefaultTimeout();
}
}); });
await StartStreamAsync(1, _browserRequestHeaders, endStream: true); await StartStreamAsync(1, _browserRequestHeaders, endStream: true);
Assert.True(firstRequestReceived.WaitOne(TimeSpan.FromSeconds(10)));
await firstRequestReceived.Task.DefaultTimeout();
await StartStreamAsync(3, _browserRequestHeaders, endStream: true); await StartStreamAsync(3, _browserRequestHeaders, endStream: true);
Assert.True(secondRequestReceived.WaitOne(TimeSpan.FromSeconds(10)));
finishSecondRequest.Set(); await secondRequestReceived.Task.DefaultTimeout();
finishSecondRequest.TrySetResult(null);
await ExpectAsync(Http2FrameType.HEADERS, await ExpectAsync(Http2FrameType.HEADERS,
withLength: 55, withLength: 55,
@ -1234,7 +1240,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
withFlags: (byte)Http2DataFrameFlags.END_STREAM, withFlags: (byte)Http2DataFrameFlags.END_STREAM,
withStreamId: 3); withStreamId: 3);
finishFirstRequest.Set(); finishFirstRequest.TrySetResult(null);
await ExpectAsync(Http2FrameType.HEADERS, await ExpectAsync(Http2FrameType.HEADERS,
withLength: 55, withLength: 55,
@ -1255,7 +1261,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
_connection.ServerSettings.MaxConcurrentStreams = 1; _connection.ServerSettings.MaxConcurrentStreams = 1;
var requestBlocker = new TaskCompletionSource<object>(); var requestBlocker = new TaskCompletionSource<object>(TaskCreationOptions.RunContinuationsAsynchronously);
await InitializeConnectionAsync(context => requestBlocker.Task); await InitializeConnectionAsync(context => requestBlocker.Task);
await StartStreamAsync(1, _browserRequestHeaders, endStream: true); await StartStreamAsync(1, _browserRequestHeaders, endStream: true);
@ -1665,7 +1671,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
{ {
// > MaxRequestHeaderCount (100) // > MaxRequestHeaderCount (100)
var headers = new List<KeyValuePair<string, string>>(); var headers = new List<KeyValuePair<string, string>>();
headers.AddRange(new [] headers.AddRange(new[]
{ {
new KeyValuePair<string, string>(HeaderNames.Method, "GET"), new KeyValuePair<string, string>(HeaderNames.Method, "GET"),
new KeyValuePair<string, string>(HeaderNames.Path, "/"), new KeyValuePair<string, string>(HeaderNames.Path, "/"),
@ -3863,7 +3869,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await SendDataAsync(1, new byte[100], endStream: true); await SendDataAsync(1, new byte[100], endStream: true);
// An extra one to break it // An extra one to break it
await SendDataAsync(1, new byte[100], endStream: true); await SendDataAsync(1, new byte[100], endStream: true);
// There's a race where either of these messages could be logged, depending on if the stream cleanup has finished yet. // There's a race where either of these messages could be logged, depending on if the stream cleanup has finished yet.
await WaitForConnectionErrorAsync<Http2ConnectionErrorException>( await WaitForConnectionErrorAsync<Http2ConnectionErrorException>(
ignoreNonGoAwayFrames: false, ignoreNonGoAwayFrames: false,

View File

@ -40,7 +40,7 @@ namespace System.Buffers
_rentTracking = rentTracking; _rentTracking = rentTracking;
_blocks = new HashSet<DiagnosticPoolBlock>(); _blocks = new HashSet<DiagnosticPoolBlock>();
_syncObj = new object(); _syncObj = new object();
_allBlocksReturned = new TaskCompletionSource<object>(); _allBlocksReturned = new TaskCompletionSource<object>(TaskCreationOptions.RunContinuationsAsynchronously);
_blockAccessExceptions = new List<Exception>(); _blockAccessExceptions = new List<Exception>();
} }