Skip to content

Commit 155b17c

Browse files
committed
Revert "Revert the output pipe in the DuplexStreamPipeAdapter (#11601)"
This reverts commit 6de357e. # Conflicts: # src/Servers/Kestrel/Core/src/Internal/Http2/Http2FrameWriter.cs # src/Servers/Kestrel/Core/src/Middleware/Internal/DuplexPipeStreamAdapter.cs
1 parent 0cebeae commit 155b17c

File tree

4 files changed

+13
-127
lines changed

4 files changed

+13
-127
lines changed

src/Servers/Kestrel/Core/src/Middleware/HttpsConnectionMiddleware.cs

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -110,10 +110,7 @@ private async Task InnerOnConnectionAsync(ConnectionContext context)
110110

111111
if (_options.ClientCertificateMode == ClientCertificateMode.NoCertificate)
112112
{
113-
sslDuplexPipe = new SslDuplexPipe(context.Transport, inputPipeOptions, outputPipeOptions)
114-
{
115-
Log = _logger
116-
};
113+
sslDuplexPipe = new SslDuplexPipe(context.Transport, inputPipeOptions, outputPipeOptions);
117114
certificateRequired = false;
118115
}
119116
else
@@ -150,10 +147,7 @@ private async Task InnerOnConnectionAsync(ConnectionContext context)
150147
}
151148

152149
return true;
153-
}))
154-
{
155-
Log = _logger
156-
};
150+
}));
157151

158152
certificateRequired = true;
159153
}

src/Servers/Kestrel/Core/src/Middleware/Internal/DuplexPipeStreamAdapter.cs

Lines changed: 10 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
using System.IO;
66
using System.IO.Pipelines;
77
using System.Threading.Tasks;
8-
using Microsoft.Extensions.Logging;
98

109
namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal
1110
{
@@ -15,127 +14,36 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal
1514
/// <typeparam name="TStream"></typeparam>
1615
internal class DuplexPipeStreamAdapter<TStream> : DuplexPipeStream, IDuplexPipe where TStream : Stream
1716
{
18-
private readonly Pipe _output;
19-
private Task _outputTask;
20-
private bool _disposed;
21-
private readonly object _disposeLock = new object();
22-
2317
public DuplexPipeStreamAdapter(IDuplexPipe duplexPipe, Func<Stream, TStream> createStream) :
2418
this(duplexPipe, new StreamPipeReaderOptions(leaveOpen: true), new StreamPipeWriterOptions(leaveOpen: true), createStream)
2519
{
2620
}
2721

28-
public DuplexPipeStreamAdapter(IDuplexPipe duplexPipe, StreamPipeReaderOptions readerOptions, StreamPipeWriterOptions writerOptions, Func<Stream, TStream> createStream) :
29-
base(duplexPipe.Input, duplexPipe.Output)
22+
public DuplexPipeStreamAdapter(IDuplexPipe duplexPipe, StreamPipeReaderOptions readerOptions, StreamPipeWriterOptions writerOptions, Func<Stream, TStream> createStream) : base(duplexPipe.Input, duplexPipe.Output)
3023
{
3124
Stream = createStream(this);
32-
33-
var outputOptions = new PipeOptions(pool: writerOptions.Pool,
34-
readerScheduler: PipeScheduler.Inline,
35-
writerScheduler: PipeScheduler.Inline,
36-
pauseWriterThreshold: 1,
37-
resumeWriterThreshold: 1,
38-
minimumSegmentSize: writerOptions.MinimumBufferSize,
39-
useSynchronizationContext: false);
40-
4125
Input = PipeReader.Create(Stream, readerOptions);
42-
43-
// We're using a pipe here because the HTTP/2 stack in Kestrel currently makes assumptions
44-
// about when it is ok to write to the PipeWriter. This should be reverted back to PipeWriter.Create once
45-
// those patterns are fixed.
46-
_output = new Pipe(outputOptions);
26+
Output = PipeWriter.Create(Stream, writerOptions);
4727
}
4828

49-
public ILogger Log { get; set; }
50-
5129
public TStream Stream { get; }
5230

5331
public PipeReader Input { get; }
5432

55-
public PipeWriter Output
56-
{
57-
get
58-
{
59-
if (_outputTask == null)
60-
{
61-
_outputTask = WriteOutputAsync();
62-
}
63-
64-
return _output.Writer;
65-
}
66-
}
33+
public PipeWriter Output { get; }
6734

68-
public override ValueTask DisposeAsync()
35+
protected override void Dispose(bool disposing)
6936
{
70-
lock (_disposeLock)
71-
{
72-
if (_disposed)
73-
{
74-
return default;
75-
}
76-
_disposed = true;
77-
}
78-
7937
Input.Complete();
80-
_output.Writer.Complete();
81-
82-
if (_outputTask == null || _outputTask.IsCompletedSuccessfully)
83-
{
84-
// Wait for the output task to complete, this ensures that we've copied
85-
// the application data to the underlying stream
86-
return default;
87-
}
88-
89-
return new ValueTask(_outputTask);
38+
Output.Complete();
39+
base.Dispose(disposing);
9040
}
9141

92-
private async Task WriteOutputAsync()
42+
public override ValueTask DisposeAsync()
9343
{
94-
try
95-
{
96-
while (true)
97-
{
98-
var result = await _output.Reader.ReadAsync();
99-
var buffer = result.Buffer;
100-
101-
try
102-
{
103-
if (buffer.IsEmpty)
104-
{
105-
if (result.IsCompleted)
106-
{
107-
break;
108-
}
109-
110-
await Stream.FlushAsync();
111-
}
112-
else if (buffer.IsSingleSegment)
113-
{
114-
await Stream.WriteAsync(buffer.First);
115-
}
116-
else
117-
{
118-
foreach (var memory in buffer)
119-
{
120-
await Stream.WriteAsync(memory);
121-
}
122-
}
123-
}
124-
finally
125-
{
126-
_output.Reader.AdvanceTo(buffer.End);
127-
}
128-
}
129-
}
130-
catch (Exception ex)
131-
{
132-
Log?.LogCritical(0, ex, $"{GetType().Name}.{nameof(WriteOutputAsync)}");
133-
}
134-
finally
135-
{
136-
_output.Reader.Complete();
137-
}
44+
Input.Complete();
45+
Output.Complete();
46+
return base.DisposeAsync();
13847
}
13948
}
14049
}
141-

src/Servers/Kestrel/Core/src/Middleware/LoggingConnectionMiddleware.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,6 @@ private class LoggingDuplexPipe : DuplexPipeStreamAdapter<LoggingStream>
4444
public LoggingDuplexPipe(IDuplexPipe transport, ILogger logger) :
4545
base(transport, stream => new LoggingStream(stream, logger))
4646
{
47-
Log = logger;
4847
}
4948
}
5049
}

src/Servers/Kestrel/test/InMemory.FunctionalTests/Http2/Http2TestBase.cs

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -444,22 +444,7 @@ protected async Task InitializeConnectionAsync(RequestDelegate application, int
444444
CreateConnection();
445445
}
446446

447-
var connectionTask = _connection.ProcessRequestsAsync(new DummyApplication(application));
448-
449-
async Task CompletePipeOnTaskCompletion()
450-
{
451-
try
452-
{
453-
await connectionTask;
454-
}
455-
finally
456-
{
457-
_pair.Transport.Input.Complete();
458-
_pair.Transport.Output.Complete();
459-
}
460-
}
461-
462-
_connectionTask = CompletePipeOnTaskCompletion();
447+
_connectionTask = _connection.ProcessRequestsAsync(new DummyApplication(application));
463448

464449
await SendPreambleAsync().ConfigureAwait(false);
465450
await SendSettingsAsync();

0 commit comments

Comments
 (0)