Fix deadlock in GOAWAY_Received_RelievesConnectionBackpressure (#2724)
This commit is contained in:
parent
429bcfe216
commit
5f065b6670
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue