Error concurrent reads gracefully

This commit is contained in:
Ben Adams 2015-12-10 15:47:46 +00:00
parent 90ece575f7
commit 9e8b07ecf8
2 changed files with 104 additions and 2 deletions

View File

@ -216,8 +216,16 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
}
else
{
// THIS IS AN ERROR STATE - ONLY ONE WAITER CAN WAIT
throw new InvalidOperationException("Concurrent reads are not supported.");
_awaitableError = new InvalidOperationException("Concurrent reads are not supported.");
awaitableState = Interlocked.Exchange(
ref _awaitableState,
_awaitableIsCompleted);
_manualResetEvent.Set();
_threadPool.Run(continuation);
_threadPool.Run(awaitableState);
}
}

View File

@ -0,0 +1,94 @@
// 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.
using System;
using System.Threading.Tasks;
using Microsoft.AspNet.Server.Kestrel;
using Microsoft.AspNet.Server.Kestrel.Http;
using Microsoft.AspNet.Server.Kestrel.Infrastructure;
using Xunit;
namespace Microsoft.AspNet.Server.KestrelTests
{
public class SocketInputTests
{
[Fact]
public async Task ConcurrentReadsFailGracefully()
{
// Arrange
var trace = new KestrelTrace(new TestKestrelTrace());
var ltp = new LoggingThreadPool(trace);
using (var memory2 = new MemoryPool2())
{
var socketInput = new SocketInput(memory2, ltp);
var task0Threw = false;
var task1Threw = false;
var task2Threw = false;
var task0 = AwaitAsTaskAsync(socketInput);
Assert.False(task0.IsFaulted);
var task = task0.ContinueWith(
(t) =>
{
TestConcurrentFaultedTask(t);
task0Threw = true;
},
TaskContinuationOptions.OnlyOnFaulted);
Assert.False(task0.IsFaulted);
// Awaiting/continuing two tasks faults both
var task1 = AwaitAsTaskAsync(socketInput);
await task1.ContinueWith(
(t) =>
{
TestConcurrentFaultedTask(t);
task1Threw = true;
},
TaskContinuationOptions.OnlyOnFaulted);
await task;
Assert.True(task0.IsFaulted);
Assert.True(task1.IsFaulted);
Assert.True(task0Threw);
Assert.True(task1Threw);
// socket stays faulted
var task2 = AwaitAsTaskAsync(socketInput);
await task2.ContinueWith(
(t) =>
{
TestConcurrentFaultedTask(t);
task2Threw = true;
},
TaskContinuationOptions.OnlyOnFaulted);
Assert.True(task2.IsFaulted);
Assert.True(task2Threw);
}
}
private static void TestConcurrentFaultedTask(Task t)
{
Assert.True(t.IsFaulted);
Assert.IsType(typeof(System.IO.IOException), t.Exception.InnerException);
Assert.Equal(t.Exception.InnerException.Message, "Concurrent reads are not supported.");
}
private async Task AwaitAsTaskAsync(SocketInput socketInput)
{
await socketInput;
}
}
}