diff --git a/src/Microsoft.AspNetCore.Server.Kestrel/Http/Frame.FeatureCollection.cs b/src/Microsoft.AspNetCore.Server.Kestrel/Http/Frame.FeatureCollection.cs index f56eb2b096..a1d03fd2b1 100644 --- a/src/Microsoft.AspNetCore.Server.Kestrel/Http/Frame.FeatureCollection.cs +++ b/src/Microsoft.AspNetCore.Server.Kestrel/Http/Frame.FeatureCollection.cs @@ -312,7 +312,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Http } } - await FlushAsync(CancellationToken.None); + await FlushAsync(default(CancellationToken)); return DuplexStream; } diff --git a/src/Microsoft.AspNetCore.Server.Kestrel/Http/Frame.cs b/src/Microsoft.AspNetCore.Server.Kestrel/Http/Frame.cs index 5f753a9558..c6b5fe05f0 100644 --- a/src/Microsoft.AspNetCore.Server.Kestrel/Http/Frame.cs +++ b/src/Microsoft.AspNetCore.Server.Kestrel/Http/Frame.cs @@ -262,7 +262,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Http Task.Factory.StartNew( (o) => ((Frame)o).RequestProcessingAsync(), this, - CancellationToken.None, + default(CancellationToken), TaskCreationOptions.DenyChildAttach, TaskScheduler.Default); } diff --git a/src/Microsoft.AspNetCore.Server.Kestrel/Http/FrameRequestStream.cs b/src/Microsoft.AspNetCore.Server.Kestrel/Http/FrameRequestStream.cs index 705045ef05..f16cf244cb 100644 --- a/src/Microsoft.AspNetCore.Server.Kestrel/Http/FrameRequestStream.cs +++ b/src/Microsoft.AspNetCore.Server.Kestrel/Http/FrameRequestStream.cs @@ -59,9 +59,9 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Http #if NET451 public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, object state) { - ValidateState(CancellationToken.None); + ValidateState(default(CancellationToken)); - var task = ReadAsync(buffer, offset, count, CancellationToken.None, state); + var task = ReadAsync(buffer, offset, count, default(CancellationToken), state); if (callback != null) { task.ContinueWith(t => callback.Invoke(t)); diff --git a/src/Microsoft.AspNetCore.Server.Kestrel/Http/FrameResponseStream.cs b/src/Microsoft.AspNetCore.Server.Kestrel/Http/FrameResponseStream.cs index f229e39305..3cf9600ecc 100644 --- a/src/Microsoft.AspNetCore.Server.Kestrel/Http/FrameResponseStream.cs +++ b/src/Microsoft.AspNetCore.Server.Kestrel/Http/FrameResponseStream.cs @@ -38,7 +38,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Http public override void Flush() { - ValidateState(CancellationToken.None); + ValidateState(default(CancellationToken)); _context.FrameControl.Flush(); } @@ -70,7 +70,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Http public override void Write(byte[] buffer, int offset, int count) { - ValidateState(CancellationToken.None); + ValidateState(default(CancellationToken)); _context.FrameControl.Write(new ArraySegment(buffer, offset, count)); } diff --git a/src/Microsoft.AspNetCore.Server.Kestrel/Http/SocketOutput.cs b/src/Microsoft.AspNetCore.Server.Kestrel/Http/SocketOutput.cs index 7033d4a1fa..3e58a4b178 100644 --- a/src/Microsoft.AspNetCore.Server.Kestrel/Http/SocketOutput.cs +++ b/src/Microsoft.AspNetCore.Server.Kestrel/Http/SocketOutput.cs @@ -474,7 +474,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Http void ISocketOutput.Write(ArraySegment buffer, bool chunk) { - WriteAsync(buffer, CancellationToken.None, chunk, isSync: true).GetAwaiter().GetResult(); + WriteAsync(buffer, default(CancellationToken), chunk, isSync: true).GetAwaiter().GetResult(); } Task ISocketOutput.WriteAsync(ArraySegment buffer, bool chunk, CancellationToken cancellationToken) diff --git a/test/Microsoft.AspNetCore.Server.KestrelTests/EngineTests.cs b/test/Microsoft.AspNetCore.Server.KestrelTests/EngineTests.cs index 811cf121a4..acfa41fb36 100644 --- a/test/Microsoft.AspNetCore.Server.KestrelTests/EngineTests.cs +++ b/test/Microsoft.AspNetCore.Server.KestrelTests/EngineTests.cs @@ -209,16 +209,16 @@ namespace Microsoft.AspNetCore.Server.KestrelTests using (var connection = new TestConnection()) { - var requestData = + var requestData = Enumerable.Repeat("GET / HTTP/1.1\r\n", loopCount) .Concat(new[] { "GET / HTTP/1.1\r\nConnection: close\r\n\r\nGoodbye" }); - var responseData = + var responseData = Enumerable.Repeat("HTTP/1.1 200 OK\r\nContent-Length: 0\r\n", loopCount) .Concat(new[] { "HTTP/1.1 200 OK\r\nConnection: close\r\n\r\nGoodbye" }); await connection.SendEnd(requestData.ToArray()); - + await connection.ReceiveEnd(responseData.ToArray()); } @@ -475,7 +475,6 @@ namespace Microsoft.AspNetCore.Server.KestrelTests { var socket = new Socket(SocketType.Stream, ProtocolType.Tcp); socket.Connect(IPAddress.Loopback, 54321); - await Task.Delay(200); socket.Dispose(); await Task.Delay(200); @@ -1096,9 +1095,8 @@ namespace Microsoft.AspNetCore.Server.KestrelTests [FrameworkSkipCondition(RuntimeFrameworks.Mono, SkipReason = "Test hangs after execution on Mono.")] public async Task FailedWritesResultInAbortedRequest(ServiceContext testContext) { - const int resetEventTimeout = 2000; // This should match _maxBytesPreCompleted in SocketOutput - const int maxBytesPreCompleted = 65536; + var maxBytesPreCompleted = 65536; // Ensure string is long enough to disable write-behind buffering var largeString = new string('a', maxBytesPreCompleted + 1); @@ -1122,9 +1120,9 @@ namespace Microsoft.AspNetCore.Server.KestrelTests try { // Ensure write is long enough to disable write-behind buffering - for (int i = 0; i < 100; i++) + for (int i = 0; i < 10; i++) { - await response.WriteAsync(largeString, lifetime.RequestAborted).ConfigureAwait(false); + await response.WriteAsync(largeString, lifetime.RequestAborted); } } catch (Exception ex) @@ -1142,7 +1140,7 @@ namespace Microsoft.AspNetCore.Server.KestrelTests "POST / HTTP/1.1", "Content-Length: 5", "", - "Hello").ConfigureAwait(false); + "Hello"); // Don't wait to receive the response. Just close the socket. } @@ -1151,7 +1149,7 @@ namespace Microsoft.AspNetCore.Server.KestrelTests // Write failed await Assert.ThrowsAsync(async () => await writeTcs.Task); // RequestAborted tripped - Assert.True(registrationWh.Wait(resetEventTimeout)); + Assert.True(registrationWh.Wait(1000)); } } diff --git a/test/Microsoft.AspNetCore.Server.KestrelTests/SocketOutputTests.cs b/test/Microsoft.AspNetCore.Server.KestrelTests/SocketOutputTests.cs index 824ab4378b..df8edab06b 100644 --- a/test/Microsoft.AspNetCore.Server.KestrelTests/SocketOutputTests.cs +++ b/test/Microsoft.AspNetCore.Server.KestrelTests/SocketOutputTests.cs @@ -119,9 +119,9 @@ namespace Microsoft.AspNetCore.Server.KestrelTests Assert.True(completedWh.Wait(1000)); } } - + [Fact] - public async Task WritesDontCompleteImmediatelyWhenTooManyBytesIncludingNonImmediateAreAlreadyPreCompleted() + public void WritesDontCompleteImmediatelyWhenTooManyBytesIncludingNonImmediateAreAlreadyPreCompleted() { // This should match _maxBytesPreCompleted in SocketOutput var maxBytesPreCompleted = 65536; @@ -155,7 +155,7 @@ namespace Microsoft.AspNetCore.Server.KestrelTests var halfWriteBehindBuffer = new ArraySegment(data, 0, bufferSize); // Act - var writeTask1 = socketOutput.WriteAsync(halfWriteBehindBuffer, CancellationToken.None); + var writeTask1 = socketOutput.WriteAsync(halfWriteBehindBuffer, default(CancellationToken)); // Assert // The first write should pre-complete since it is <= _maxBytesPreCompleted. Assert.Equal(TaskStatus.RanToCompletion, writeTask1.Status); @@ -168,7 +168,7 @@ namespace Microsoft.AspNetCore.Server.KestrelTests socketOutput.ProducingComplete(iter); // Act - var writeTask2 = socketOutput.WriteAsync(halfWriteBehindBuffer, CancellationToken.None); + var writeTask2 = socketOutput.WriteAsync(halfWriteBehindBuffer, default(CancellationToken)); // Assert // Too many bytes are already pre-completed for the fourth write to pre-complete. Assert.True(writeRequestedWh.Wait(1000)); @@ -230,15 +230,12 @@ namespace Microsoft.AspNetCore.Server.KestrelTests Assert.False(task1Success.IsCanceled); Assert.False(task1Success.IsFaulted); - task1Success.GetAwaiter().GetResult(); - // following tasks should wait. - var task2Throw = socketOutput.WriteAsync(fullBuffer, cancellationToken: cts.Token); var task3Success = socketOutput.WriteAsync(fullBuffer, cancellationToken: default(CancellationToken)); // Give time for tasks to percolate - await Task.Delay(1000).ConfigureAwait(false); + await Task.Delay(1000); // Second task is not completed Assert.False(task2Throw.IsCompleted); @@ -252,18 +249,12 @@ namespace Microsoft.AspNetCore.Server.KestrelTests cts.Cancel(); - // Give time for tasks to percolate - await Task.Delay(1000).ConfigureAwait(false); - // Second task is now canceled - Assert.True(task2Throw.IsCompleted); + await Assert.ThrowsAsync(() => task2Throw); Assert.True(task2Throw.IsCanceled); - Assert.False(task2Throw.IsFaulted); - // Third task is now completed - Assert.True(task3Success.IsCompleted); - Assert.False(task3Success.IsCanceled); - Assert.False(task3Success.IsFaulted); + // Third task is now completed + await task3Success; // Fourth task immediately cancels as the token is canceled var task4Throw = socketOutput.WriteAsync(fullBuffer, cancellationToken: cts.Token); @@ -272,25 +263,21 @@ namespace Microsoft.AspNetCore.Server.KestrelTests Assert.True(task4Throw.IsCanceled); Assert.False(task4Throw.IsFaulted); - Assert.Throws(() => task4Throw.GetAwaiter().GetResult()); - var task5Success = socketOutput.WriteAsync(fullBuffer, cancellationToken: default(CancellationToken)); // task5 should complete immediately - + Assert.True(task5Success.IsCompleted); Assert.False(task5Success.IsCanceled); Assert.False(task5Success.IsFaulted); cts = new CancellationTokenSource(); - var task6Throw = socketOutput.WriteAsync(fullBuffer, cancellationToken: cts.Token); + var task6Success = socketOutput.WriteAsync(fullBuffer, cancellationToken: cts.Token); // task6 should complete immediately but not cancel as its cancellation token isn't set - Assert.True(task6Throw.IsCompleted); - Assert.False(task6Throw.IsCanceled); - Assert.False(task6Throw.IsFaulted); - - task6Throw.GetAwaiter().GetResult(); + Assert.True(task6Success.IsCompleted); + Assert.False(task6Success.IsCanceled); + Assert.False(task6Success.IsFaulted); Assert.True(true); } @@ -342,14 +329,12 @@ namespace Microsoft.AspNetCore.Server.KestrelTests Assert.False(task1Success.IsCanceled); Assert.False(task1Success.IsFaulted); - task1Success.GetAwaiter().GetResult(); - // following tasks should wait. - var task2Success = socketOutput.WriteAsync(fullBuffer, cancellationToken: CancellationToken.None); + var task2Success = socketOutput.WriteAsync(fullBuffer, cancellationToken: default(CancellationToken)); var task3Canceled = socketOutput.WriteAsync(fullBuffer, cancellationToken: abortedSource.Token); // Give time for tasks to percolate - await Task.Delay(1000).ConfigureAwait(false); + await Task.Delay(1000); // Second task is not completed Assert.False(task2Success.IsCompleted); @@ -364,18 +349,12 @@ namespace Microsoft.AspNetCore.Server.KestrelTests // Cause the first write to fail. completeQueue.Dequeue()(-1); - // Give time for tasks to percolate - await Task.Delay(1000).ConfigureAwait(false); - // Second task is now completed - Assert.True(task2Success.IsCompleted); - Assert.False(task2Success.IsCanceled); - Assert.False(task2Success.IsFaulted); + await task2Success; // Third task is now canceled - Assert.True(task3Canceled.IsCompleted); + await Assert.ThrowsAsync(() => task3Canceled); Assert.True(task3Canceled.IsCanceled); - Assert.False(task3Canceled.IsFaulted); } } diff --git a/test/Microsoft.AspNetCore.Server.KestrelTests/TestConnection.cs b/test/Microsoft.AspNetCore.Server.KestrelTests/TestConnection.cs index 268eaa7b78..b7a2a625cb 100644 --- a/test/Microsoft.AspNetCore.Server.KestrelTests/TestConnection.cs +++ b/test/Microsoft.AspNetCore.Server.KestrelTests/TestConnection.cs @@ -49,7 +49,8 @@ namespace Microsoft.AspNetCore.Server.KestrelTests var ch = text[index]; await writer.WriteAsync(ch); await writer.FlushAsync(); - await Task.Delay(TimeSpan.FromMilliseconds(5)); + // Re-add delay to help find socket input consumption bugs more consistently + //await Task.Delay(TimeSpan.FromMilliseconds(5)); } writer.Flush(); _stream.Flush();