Await dispose for inner stream before disposing SslStream. (#11819)
This commit is contained in:
parent
59d636f6bd
commit
401a90633b
|
|
@ -234,8 +234,11 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Https.Internal
|
||||||
|
|
||||||
// Disposing the stream will dispose the sslDuplexPipe
|
// Disposing the stream will dispose the sslDuplexPipe
|
||||||
await using (sslStream)
|
await using (sslStream)
|
||||||
|
await using (sslDuplexPipe)
|
||||||
{
|
{
|
||||||
await _next(context);
|
await _next(context);
|
||||||
|
// Dispose the inner stream (SslDuplexPipe) before disposing the SslStream
|
||||||
|
// as the duplex pipe can hit an ODE as it still may be writing.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal
|
||||||
{
|
{
|
||||||
private readonly Pipe _output;
|
private readonly Pipe _output;
|
||||||
private Task _outputTask;
|
private Task _outputTask;
|
||||||
|
private bool _disposed;
|
||||||
|
private readonly object _disposeLock = new object();
|
||||||
|
|
||||||
public DuplexPipeStreamAdapter(IDuplexPipe duplexPipe, Func<Stream, TStream> createStream) :
|
public DuplexPipeStreamAdapter(IDuplexPipe duplexPipe, Func<Stream, TStream> createStream) :
|
||||||
this(duplexPipe, new StreamPipeReaderOptions(leaveOpen: true), new StreamPipeWriterOptions(leaveOpen: true), createStream)
|
this(duplexPipe, new StreamPipeReaderOptions(leaveOpen: true), new StreamPipeWriterOptions(leaveOpen: true), createStream)
|
||||||
|
|
@ -63,17 +65,28 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async ValueTask DisposeAsync()
|
public override ValueTask DisposeAsync()
|
||||||
{
|
{
|
||||||
|
lock (_disposeLock)
|
||||||
|
{
|
||||||
|
if (_disposed)
|
||||||
|
{
|
||||||
|
return default;
|
||||||
|
}
|
||||||
|
_disposed = true;
|
||||||
|
}
|
||||||
|
|
||||||
Input.Complete();
|
Input.Complete();
|
||||||
_output.Writer.Complete();
|
_output.Writer.Complete();
|
||||||
|
|
||||||
if (_outputTask != null)
|
if (_outputTask == null || _outputTask.IsCompletedSuccessfully)
|
||||||
{
|
{
|
||||||
// Wait for the output task to complete, this ensures that we've copied
|
// Wait for the output task to complete, this ensures that we've copied
|
||||||
// the application data to the underlying stream
|
// the application data to the underlying stream
|
||||||
await _outputTask;
|
return default;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return new ValueTask(_outputTask);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task WriteOutputAsync()
|
private async Task WriteOutputAsync()
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue