diff --git a/src/Servers/Kestrel/Core/src/Internal/Http2/Http2OutputProducer.cs b/src/Servers/Kestrel/Core/src/Internal/Http2/Http2OutputProducer.cs index 0f95f70ef7..cc30a8ee66 100644 --- a/src/Servers/Kestrel/Core/src/Internal/Http2/Http2OutputProducer.cs +++ b/src/Servers/Kestrel/Core/src/Internal/Http2/Http2OutputProducer.cs @@ -41,10 +41,10 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2 private bool _suffixSent; private bool _streamEnded; private bool _writerComplete; - private bool _disposed; // Internal for testing internal ValueTask _dataWriteProcessingTask; + internal bool _disposed; /// The core logic for the IValueTaskSource implementation. private ManualResetValueTaskSourceCore _responseCompleteTaskSource = new ManualResetValueTaskSourceCore { RunContinuationsAsynchronously = true }; // mutable struct, do not make this readonly diff --git a/src/Servers/Kestrel/test/InMemory.FunctionalTests/Http2/Http2ConnectionTests.cs b/src/Servers/Kestrel/test/InMemory.FunctionalTests/Http2/Http2ConnectionTests.cs index 1a7bd27c24..f7426ef669 100644 --- a/src/Servers/Kestrel/test/InMemory.FunctionalTests/Http2/Http2ConnectionTests.cs +++ b/src/Servers/Kestrel/test/InMemory.FunctionalTests/Http2/Http2ConnectionTests.cs @@ -486,12 +486,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests withStreamId: 1); await WaitForStreamErrorAsync(1, Http2ErrorCode.INTERNAL_ERROR, null); - // Ping will trigger the stream to be returned to the pool so we can assert it - await SendPingAsync(Http2PingFrameFlags.NONE); - await ExpectAsync(Http2FrameType.PING, - withLength: 8, - withFlags: (byte)Http2PingFrameFlags.ACK, - withStreamId: 0); + await PingUntilStreamDisposed(stream).DefaultTimeout(); // Stream is not returned to the pool Assert.Equal(0, _connection.StreamPool.Count); @@ -500,6 +495,21 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests await output._dataWriteProcessingTask.DefaultTimeout(); await StopConnectionAsync(expectedLastStreamId: 1, ignoreNonGoAwayFrames: false); + + async Task PingUntilStreamDisposed(Http2Stream stream) + { + var output = (Http2OutputProducer)stream.Output; + + do + { + // Ping will trigger the stream to be returned to the pool so we can assert it + await SendPingAsync(Http2PingFrameFlags.NONE); + await ExpectAsync(Http2FrameType.PING, + withLength: 8, + withFlags: (byte)Http2PingFrameFlags.ACK, + withStreamId: 0); + } while (!output._disposed); + } } [Fact]