Fix deadlock in GOAWAY_Received_RelievesConnectionBackpressure (#2724)

This commit is contained in:
Stephen Halter 2018-07-16 10:55:09 -07:00 committed by GitHub
parent 429bcfe216
commit 5f065b6670
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 11 additions and 20 deletions

View File

@ -131,14 +131,23 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
public Http2ConnectionTests() public Http2ConnectionTests()
{ {
var inlineSchedulingPipeOptions = new PipeOptions( // Always dispatch test code back to the ThreadPool. This prevents deadlocks caused by continuing
// Http2Connection.ProcessRequestsAsync() loop with writer locks acquired. Run product code inline to make
// it easier to verify request frames are processed correctly immediately after sending the them.
var inputPipeOptions = new PipeOptions(
pool: _memoryPool, pool: _memoryPool,
readerScheduler: PipeScheduler.Inline, readerScheduler: PipeScheduler.Inline,
writerScheduler: PipeScheduler.ThreadPool,
useSynchronizationContext: false
);
var outputPipeOptions = new PipeOptions(
pool: _memoryPool,
readerScheduler: PipeScheduler.ThreadPool,
writerScheduler: PipeScheduler.Inline, writerScheduler: PipeScheduler.Inline,
useSynchronizationContext: false useSynchronizationContext: false
); );
_pair = DuplexPipe.CreateConnectionPair(inlineSchedulingPipeOptions, inlineSchedulingPipeOptions); _pair = DuplexPipe.CreateConnectionPair(inputPipeOptions, outputPipeOptions);
_noopApplication = context => Task.CompletedTask; _noopApplication = context => Task.CompletedTask;
@ -488,12 +497,6 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
withFlags: (byte)Http2DataFrameFlags.END_STREAM, withFlags: (byte)Http2DataFrameFlags.END_STREAM,
withStreamId: 3); withStreamId: 3);
// Ensure that Http2FrameWriter._writeLock isn't acquired when completing the frame processing loop.
// Otherwise there's a deadlock where Http2OutputProducer.Abort() being called from the frame processing
// loop blocks waiting Http2OutputProducer.Dispose() being called from the stream processing loop to
// acquire the _writeLock.
await ThreadPoolAwaitable.Instance;
await StopConnectionAsync(expectedLastStreamId: 3, ignoreNonGoAwayFrames: false); await StopConnectionAsync(expectedLastStreamId: 3, ignoreNonGoAwayFrames: false);
Assert.Equal(stream1DataFrame1.DataPayload, _helloBytes); Assert.Equal(stream1DataFrame1.DataPayload, _helloBytes);
@ -565,12 +568,6 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
withFlags: (byte)Http2DataFrameFlags.END_STREAM, withFlags: (byte)Http2DataFrameFlags.END_STREAM,
withStreamId: 1); withStreamId: 1);
// Ensure that Http2FrameWriter._writeLock isn't acquired when completing the frame processing loop.
// Otherwise there's a deadlock where Http2OutputProducer.Abort() being called from the frame processing
// loop blocks waiting Http2OutputProducer.Dispose() being called from the stream processing loop to
// acquire the _writeLock.
await ThreadPoolAwaitable.Instance;
await StopConnectionAsync(expectedLastStreamId: 3, ignoreNonGoAwayFrames: false); await StopConnectionAsync(expectedLastStreamId: 3, ignoreNonGoAwayFrames: false);
} }
@ -868,12 +865,6 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
withFlags: (byte)Http2DataFrameFlags.END_STREAM, withFlags: (byte)Http2DataFrameFlags.END_STREAM,
withStreamId: 1); withStreamId: 1);
// Ensure that Http2FrameWriter._writeLock isn't acquired when completing the frame processing loop.
// Otherwise there's a deadlock where Http2OutputProducer.Abort() being called from the frame processing
// loop blocks waiting Http2OutputProducer.Dispose() being called from the stream processing loop to
// acquire the _writeLock.
await ThreadPoolAwaitable.Instance;
await StopConnectionAsync(expectedLastStreamId: 3, ignoreNonGoAwayFrames: false); await StopConnectionAsync(expectedLastStreamId: 3, ignoreNonGoAwayFrames: false);
await WaitForAllStreamsAsync(); await WaitForAllStreamsAsync();
} }