More FrameConnection refactoring (#1820)
* More FrameConnection refactoring - This change reverts the change to complete the writer with an exception on abort because of the number of first chance exceptions that get thrown. - This change also moves connection logging into FrameConnection instead of being split between the ConnectionHandler and FrameConnection. - Fixed issues with LibuvOutputConsumerTests that leak WriteReq since cancelled writes no longer end the connection.
This commit is contained in:
parent
c48113ad80
commit
c8b6a2be56
|
|
@ -7,7 +7,6 @@ using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http;
|
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http;
|
||||||
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure;
|
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure;
|
||||||
using Microsoft.AspNetCore.Server.Kestrel.Internal.System.IO.Pipelines;
|
using Microsoft.AspNetCore.Server.Kestrel.Internal.System.IO.Pipelines;
|
||||||
using Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions;
|
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.Kestrel.Core.Adapter.Internal
|
namespace Microsoft.AspNetCore.Server.Kestrel.Core.Adapter.Internal
|
||||||
{
|
{
|
||||||
|
|
@ -16,17 +15,17 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Adapter.Internal
|
||||||
private const int MinAllocBufferSize = 2048;
|
private const int MinAllocBufferSize = 2048;
|
||||||
|
|
||||||
private readonly IKestrelTrace _trace;
|
private readonly IKestrelTrace _trace;
|
||||||
private readonly IPipeWriter _transportOutputPipeWriter;
|
private readonly IPipe _transportOutputPipe;
|
||||||
private readonly IPipeReader _transportInputPipeReader;
|
private readonly IPipeReader _transportInputPipeReader;
|
||||||
|
|
||||||
public AdaptedPipeline(IPipeReader transportInputPipeReader,
|
public AdaptedPipeline(IPipeReader transportInputPipeReader,
|
||||||
IPipeWriter transportOutputPipeWriter,
|
IPipe transportOutputPipe,
|
||||||
IPipe inputPipe,
|
IPipe inputPipe,
|
||||||
IPipe outputPipe,
|
IPipe outputPipe,
|
||||||
IKestrelTrace trace)
|
IKestrelTrace trace)
|
||||||
{
|
{
|
||||||
_transportInputPipeReader = transportInputPipeReader;
|
_transportInputPipeReader = transportInputPipeReader;
|
||||||
_transportOutputPipeWriter = transportOutputPipeWriter;
|
_transportOutputPipe = transportOutputPipe;
|
||||||
Input = inputPipe;
|
Input = inputPipe;
|
||||||
Output = outputPipe;
|
Output = outputPipe;
|
||||||
_trace = trace;
|
_trace = trace;
|
||||||
|
|
@ -58,18 +57,24 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Adapter.Internal
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
var readResult = await Output.Reader.ReadAsync();
|
var result = await Output.Reader.ReadAsync();
|
||||||
var buffer = readResult.Buffer;
|
var buffer = result.Buffer;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (buffer.IsEmpty && readResult.IsCompleted)
|
if (result.IsCancelled)
|
||||||
{
|
{
|
||||||
|
// Forward the cancellation to the transport pipe
|
||||||
|
_transportOutputPipe.Reader.CancelPendingRead();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (buffer.IsEmpty)
|
if (buffer.IsEmpty)
|
||||||
{
|
{
|
||||||
|
if (result.IsCompleted)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
await stream.FlushAsync();
|
await stream.FlushAsync();
|
||||||
}
|
}
|
||||||
else if (buffer.IsSingleSpan)
|
else if (buffer.IsSingleSpan)
|
||||||
|
|
@ -99,7 +104,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Adapter.Internal
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
Output.Reader.Complete();
|
Output.Reader.Complete();
|
||||||
_transportOutputPipeWriter.Complete(error);
|
_transportOutputPipe.Writer.Complete(error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -111,8 +116,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Adapter.Internal
|
||||||
{
|
{
|
||||||
if (stream == null)
|
if (stream == null)
|
||||||
{
|
{
|
||||||
// If the stream is null then we're going to abort the connection
|
// REVIEW: Do we need an exception here?
|
||||||
throw new ConnectionAbortedException();
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
|
|
|
||||||
|
|
@ -47,16 +47,13 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal
|
||||||
ConnectionId = connectionId,
|
ConnectionId = connectionId,
|
||||||
FrameConnectionId = frameConnectionId,
|
FrameConnectionId = frameConnectionId,
|
||||||
ServiceContext = _serviceContext,
|
ServiceContext = _serviceContext,
|
||||||
PipeFactory = connectionInfo.PipeFactory,
|
ConnectionInformation = connectionInfo,
|
||||||
ConnectionAdapters = _listenOptions.ConnectionAdapters,
|
ConnectionAdapters = _listenOptions.ConnectionAdapters,
|
||||||
Frame = frame,
|
Frame = frame,
|
||||||
Input = inputPipe,
|
Input = inputPipe,
|
||||||
Output = outputPipe,
|
Output = outputPipe,
|
||||||
});
|
});
|
||||||
|
|
||||||
_serviceContext.Log.ConnectionStart(connectionId);
|
|
||||||
KestrelEventSource.Log.ConnectionStart(connection, connectionInfo);
|
|
||||||
|
|
||||||
// Since data cannot be added to the inputPipe by the transport until OnConnection returns,
|
// Since data cannot be added to the inputPipe by the transport until OnConnection returns,
|
||||||
// Frame.ProcessRequestsAsync is guaranteed to unblock the transport thread before calling
|
// Frame.ProcessRequestsAsync is guaranteed to unblock the transport thread before calling
|
||||||
// application code.
|
// application code.
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal
|
||||||
public IPipeWriter Input => _context.Input.Writer;
|
public IPipeWriter Input => _context.Input.Writer;
|
||||||
public IPipeReader Output => _context.Output.Reader;
|
public IPipeReader Output => _context.Output.Reader;
|
||||||
|
|
||||||
private PipeFactory PipeFactory => _context.PipeFactory;
|
private PipeFactory PipeFactory => _context.ConnectionInformation.PipeFactory;
|
||||||
|
|
||||||
// Internal for testing
|
// Internal for testing
|
||||||
internal PipeOptions AdaptedInputPipeOptions => new PipeOptions
|
internal PipeOptions AdaptedInputPipeOptions => new PipeOptions
|
||||||
|
|
@ -70,21 +70,24 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
Log.ConnectionStart(ConnectionId);
|
||||||
|
KestrelEventSource.Log.ConnectionStart(this, _context.ConnectionInformation);
|
||||||
|
|
||||||
AdaptedPipeline adaptedPipeline = null;
|
AdaptedPipeline adaptedPipeline = null;
|
||||||
var adaptedPipelineTask = Task.CompletedTask;
|
var adaptedPipelineTask = Task.CompletedTask;
|
||||||
var input = _context.Input.Reader;
|
var input = _context.Input.Reader;
|
||||||
var output = _context.Output.Writer;
|
var output = _context.Output;
|
||||||
|
|
||||||
if (_connectionAdapters.Count > 0)
|
if (_connectionAdapters.Count > 0)
|
||||||
{
|
{
|
||||||
adaptedPipeline = new AdaptedPipeline(_context.Input.Reader,
|
adaptedPipeline = new AdaptedPipeline(input,
|
||||||
_context.Output.Writer,
|
output,
|
||||||
PipeFactory.Create(AdaptedInputPipeOptions),
|
PipeFactory.Create(AdaptedInputPipeOptions),
|
||||||
PipeFactory.Create(AdaptedOutputPipeOptions),
|
PipeFactory.Create(AdaptedOutputPipeOptions),
|
||||||
Log);
|
Log);
|
||||||
|
|
||||||
input = adaptedPipeline.Input.Reader;
|
input = adaptedPipeline.Input.Reader;
|
||||||
output = adaptedPipeline.Output.Writer;
|
output = adaptedPipeline.Output;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set these before the first await, this is to make sure that we don't yield control
|
// Set these before the first await, this is to make sure that we don't yield control
|
||||||
|
|
@ -114,6 +117,9 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal
|
||||||
{
|
{
|
||||||
_context.ServiceContext.ConnectionManager.RemoveConnection(_context.FrameConnectionId);
|
_context.ServiceContext.ConnectionManager.RemoveConnection(_context.FrameConnectionId);
|
||||||
DisposeAdaptedConnections();
|
DisposeAdaptedConnections();
|
||||||
|
|
||||||
|
Log.ConnectionStop(ConnectionId);
|
||||||
|
KestrelEventSource.Log.ConnectionStop(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -122,8 +128,6 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal
|
||||||
// Abort the connection (if not already aborted)
|
// Abort the connection (if not already aborted)
|
||||||
_frame.Abort(ex);
|
_frame.Abort(ex);
|
||||||
|
|
||||||
Log.ConnectionStop(ConnectionId);
|
|
||||||
KestrelEventSource.Log.ConnectionStop(this);
|
|
||||||
_socketClosedTcs.TrySetResult(null);
|
_socketClosedTcs.TrySetResult(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ using System.Collections.Generic;
|
||||||
using Microsoft.AspNetCore.Server.Kestrel.Core.Adapter.Internal;
|
using Microsoft.AspNetCore.Server.Kestrel.Core.Adapter.Internal;
|
||||||
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http;
|
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http;
|
||||||
using Microsoft.AspNetCore.Server.Kestrel.Internal.System.IO.Pipelines;
|
using Microsoft.AspNetCore.Server.Kestrel.Internal.System.IO.Pipelines;
|
||||||
|
using Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal
|
namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal
|
||||||
{
|
{
|
||||||
|
|
@ -13,8 +14,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal
|
||||||
public string ConnectionId { get; set; }
|
public string ConnectionId { get; set; }
|
||||||
public long FrameConnectionId { get; set; }
|
public long FrameConnectionId { get; set; }
|
||||||
public ServiceContext ServiceContext { get; set; }
|
public ServiceContext ServiceContext { get; set; }
|
||||||
public PipeFactory PipeFactory { get; set; }
|
|
||||||
public List<IConnectionAdapter> ConnectionAdapters { get; set; }
|
public List<IConnectionAdapter> ConnectionAdapters { get; set; }
|
||||||
|
public IConnectionInformation ConnectionInformation { get; set; }
|
||||||
public Frame Frame { get; set; }
|
public Frame Frame { get; set; }
|
||||||
|
|
||||||
public IPipe Input { get; set; }
|
public IPipe Input { get; set; }
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,6 @@ using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure;
|
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure;
|
||||||
using Microsoft.AspNetCore.Server.Kestrel.Internal.System.IO.Pipelines;
|
using Microsoft.AspNetCore.Server.Kestrel.Internal.System.IO.Pipelines;
|
||||||
using Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions;
|
|
||||||
using Microsoft.Extensions.Internal;
|
using Microsoft.Extensions.Internal;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
||||||
|
|
@ -21,10 +20,9 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
||||||
// This locks access to to all of the below fields
|
// This locks access to to all of the below fields
|
||||||
private readonly object _contextLock = new object();
|
private readonly object _contextLock = new object();
|
||||||
|
|
||||||
private bool _cancelled = false;
|
|
||||||
private bool _completed = false;
|
private bool _completed = false;
|
||||||
|
|
||||||
private readonly IPipeWriter _pipe;
|
private readonly IPipe _pipe;
|
||||||
|
|
||||||
// https://github.com/dotnet/corefxlab/issues/1334
|
// https://github.com/dotnet/corefxlab/issues/1334
|
||||||
// Pipelines don't support multiple awaiters on flush
|
// Pipelines don't support multiple awaiters on flush
|
||||||
|
|
@ -33,7 +31,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
||||||
private readonly object _flushLock = new object();
|
private readonly object _flushLock = new object();
|
||||||
private Action _flushCompleted;
|
private Action _flushCompleted;
|
||||||
|
|
||||||
public OutputProducer(IPipeWriter pipe, string connectionId, IKestrelTrace log)
|
public OutputProducer(IPipe pipe, string connectionId, IKestrelTrace log)
|
||||||
{
|
{
|
||||||
_pipe = pipe;
|
_pipe = pipe;
|
||||||
_connectionId = connectionId;
|
_connectionId = connectionId;
|
||||||
|
|
@ -50,13 +48,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
||||||
{
|
{
|
||||||
if (cancellationToken.IsCancellationRequested)
|
if (cancellationToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
_cancelled = true;
|
|
||||||
return Task.FromCanceled(cancellationToken);
|
return Task.FromCanceled(cancellationToken);
|
||||||
}
|
}
|
||||||
else if (_cancelled)
|
|
||||||
{
|
|
||||||
return TaskCache.CompletedTask;
|
|
||||||
}
|
|
||||||
|
|
||||||
return WriteAsync(buffer, cancellationToken, chunk);
|
return WriteAsync(buffer, cancellationToken, chunk);
|
||||||
}
|
}
|
||||||
|
|
@ -80,7 +73,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var buffer = _pipe.Alloc(1);
|
var buffer = _pipe.Writer.Alloc(1);
|
||||||
callback(buffer, state);
|
callback(buffer, state);
|
||||||
buffer.Commit();
|
buffer.Commit();
|
||||||
}
|
}
|
||||||
|
|
@ -97,7 +90,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
||||||
|
|
||||||
_log.ConnectionDisconnect(_connectionId);
|
_log.ConnectionDisconnect(_connectionId);
|
||||||
_completed = true;
|
_completed = true;
|
||||||
_pipe.Complete();
|
_pipe.Writer.Complete();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -112,7 +105,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
||||||
|
|
||||||
_log.ConnectionDisconnect(_connectionId);
|
_log.ConnectionDisconnect(_connectionId);
|
||||||
_completed = true;
|
_completed = true;
|
||||||
_pipe.Complete(new ConnectionAbortedException());
|
_pipe.Reader.CancelPendingRead();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -130,7 +123,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
||||||
return TaskCache.CompletedTask;
|
return TaskCache.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
writableBuffer = _pipe.Alloc(1);
|
writableBuffer = _pipe.Writer.Alloc(1);
|
||||||
var writer = new WritableBufferWriter(writableBuffer);
|
var writer = new WritableBufferWriter(writableBuffer);
|
||||||
if (buffer.Count > 0)
|
if (buffer.Count > 0)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -37,50 +37,47 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
|
var result = await _pipe.ReadAsync();
|
||||||
|
var buffer = result.Buffer;
|
||||||
|
var consumed = buffer.End;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var result = await _pipe.ReadAsync();
|
if (result.IsCancelled)
|
||||||
var buffer = result.Buffer;
|
|
||||||
var consumed = buffer.End;
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
{
|
||||||
if (!buffer.IsEmpty)
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!buffer.IsEmpty)
|
||||||
|
{
|
||||||
|
var writeReq = pool.Allocate();
|
||||||
|
|
||||||
|
try
|
||||||
{
|
{
|
||||||
var writeReq = pool.Allocate();
|
var writeResult = await writeReq.WriteAsync(_socket, buffer);
|
||||||
|
|
||||||
try
|
LogWriteInfo(writeResult.Status, writeResult.Error);
|
||||||
|
|
||||||
|
if (writeResult.Error != null)
|
||||||
{
|
{
|
||||||
var writeResult = await writeReq.WriteAsync(_socket, buffer);
|
consumed = buffer.Start;
|
||||||
|
throw writeResult.Error;
|
||||||
LogWriteInfo(writeResult.Status, writeResult.Error);
|
|
||||||
|
|
||||||
if (writeResult.Error != null)
|
|
||||||
{
|
|
||||||
consumed = buffer.Start;
|
|
||||||
throw writeResult.Error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
// Make sure we return the writeReq to the pool
|
|
||||||
pool.Return(writeReq);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
finally
|
||||||
if (buffer.IsEmpty && result.IsCompleted)
|
|
||||||
{
|
{
|
||||||
break;
|
// Make sure we return the writeReq to the pool
|
||||||
|
pool.Return(writeReq);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
finally
|
else if (result.IsCompleted)
|
||||||
{
|
{
|
||||||
_pipe.Advance(consumed);
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (ConnectionAbortedException)
|
finally
|
||||||
{
|
{
|
||||||
break;
|
_pipe.Advance(consumed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -167,6 +167,11 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets
|
||||||
var result = await _output.ReadAsync();
|
var result = await _output.ReadAsync();
|
||||||
var buffer = result.Buffer;
|
var buffer = result.Buffer;
|
||||||
|
|
||||||
|
if (result.IsCancelled)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (!buffer.IsEmpty)
|
if (!buffer.IsEmpty)
|
||||||
|
|
@ -189,15 +194,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (result.IsCompleted)
|
||||||
if (result.IsCancelled)
|
|
||||||
{
|
|
||||||
// Send a FIN
|
|
||||||
_socket.Shutdown(SocketShutdown.Send);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (buffer.IsEmpty && result.IsCompleted)
|
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -207,6 +204,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets
|
||||||
_output.Advance(buffer.End);
|
_output.Advance(buffer.End);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_socket.Shutdown(SocketShutdown.Send);
|
||||||
}
|
}
|
||||||
catch (SocketException ex) when (ex.SocketErrorCode == SocketError.OperationAborted)
|
catch (SocketException ex) when (ex.SocketErrorCode == SocketError.OperationAborted)
|
||||||
{
|
{
|
||||||
|
|
@ -216,10 +215,6 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets
|
||||||
{
|
{
|
||||||
error = null;
|
error = null;
|
||||||
}
|
}
|
||||||
catch (ConnectionAbortedException)
|
|
||||||
{
|
|
||||||
error = null;
|
|
||||||
}
|
|
||||||
catch (IOException ex)
|
catch (IOException ex)
|
||||||
{
|
{
|
||||||
error = ex;
|
error = ex;
|
||||||
|
|
|
||||||
|
|
@ -70,7 +70,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
||||||
TimeoutControl = Mock.Of<ITimeoutControl>()
|
TimeoutControl = Mock.Of<ITimeoutControl>()
|
||||||
};
|
};
|
||||||
|
|
||||||
_frame.Output = new OutputProducer(output.Writer, "", Mock.Of<IKestrelTrace>());
|
_frame.Output = new OutputProducer(output, "", Mock.Of<IKestrelTrace>());
|
||||||
|
|
||||||
_frame.Reset();
|
_frame.Reset();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
||||||
var pipe = _pipeFactory.Create(pipeOptions);
|
var pipe = _pipeFactory.Create(pipeOptions);
|
||||||
var serviceContext = new TestServiceContext();
|
var serviceContext = new TestServiceContext();
|
||||||
var frame = new Frame<object>(null, new FrameContext { ServiceContext = serviceContext });
|
var frame = new Frame<object>(null, new FrameContext { ServiceContext = serviceContext });
|
||||||
var socketOutput = new OutputProducer(pipe.Writer, "0", serviceContext.Log);
|
var socketOutput = new OutputProducer(pipe, "0", serviceContext.Log);
|
||||||
|
|
||||||
return socketOutput;
|
return socketOutput;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -109,7 +109,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
|
||||||
Input = input.Reader,
|
Input = input.Reader,
|
||||||
};
|
};
|
||||||
|
|
||||||
frame.Output = new OutputProducer(output.Writer, "", null);
|
frame.Output = new OutputProducer(output, "", null);
|
||||||
|
|
||||||
frame.Reset();
|
frame.Reset();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -131,7 +131,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
|
||||||
{
|
{
|
||||||
Input = input.Reader,
|
Input = input.Reader,
|
||||||
};
|
};
|
||||||
frame.Output = new OutputProducer(output.Writer, "", null);
|
frame.Output = new OutputProducer(output, "", null);
|
||||||
|
|
||||||
frame.Reset();
|
frame.Reset();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -392,6 +392,14 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests
|
||||||
Assert.True(task3Canceled.IsCanceled);
|
Assert.True(task3Canceled.IsCanceled);
|
||||||
|
|
||||||
Assert.True(abortedSource.IsCancellationRequested);
|
Assert.True(abortedSource.IsCancellationRequested);
|
||||||
|
|
||||||
|
await _mockLibuv.OnPostTask;
|
||||||
|
|
||||||
|
// Complete the 4th write
|
||||||
|
while (completeQueue.TryDequeue(out var triggerNextCompleted))
|
||||||
|
{
|
||||||
|
await _libuvThread.PostAsync(cb => cb(0), triggerNextCompleted);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -467,6 +475,14 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests
|
||||||
Assert.True(task3Canceled.IsCanceled);
|
Assert.True(task3Canceled.IsCanceled);
|
||||||
|
|
||||||
Assert.True(abortedSource.IsCancellationRequested);
|
Assert.True(abortedSource.IsCancellationRequested);
|
||||||
|
|
||||||
|
await _mockLibuv.OnPostTask;
|
||||||
|
|
||||||
|
// Complete the 4th write
|
||||||
|
while (completeQueue.TryDequeue(out var triggerNextCompleted))
|
||||||
|
{
|
||||||
|
await _libuvThread.PostAsync(cb => cb(0), triggerNextCompleted);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -544,6 +560,14 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests
|
||||||
// Third task is now canceled
|
// Third task is now canceled
|
||||||
await Assert.ThrowsAsync<OperationCanceledException>(() => task3Canceled);
|
await Assert.ThrowsAsync<OperationCanceledException>(() => task3Canceled);
|
||||||
Assert.True(task3Canceled.IsCanceled);
|
Assert.True(task3Canceled.IsCanceled);
|
||||||
|
|
||||||
|
await _mockLibuv.OnPostTask;
|
||||||
|
|
||||||
|
// Complete the 4th write
|
||||||
|
while (completeQueue.TryDequeue(out var triggerNextCompleted))
|
||||||
|
{
|
||||||
|
await _libuvThread.PostAsync(cb => cb(0), triggerNextCompleted);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -586,6 +610,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests
|
||||||
var writeTask2 = socketOutput.WriteAsync(buffer);
|
var writeTask2 = socketOutput.WriteAsync(buffer);
|
||||||
var writeTask3 = socketOutput.WriteAsync(buffer);
|
var writeTask3 = socketOutput.WriteAsync(buffer);
|
||||||
|
|
||||||
|
await _mockLibuv.OnPostTask;
|
||||||
|
|
||||||
// Drain the write queue
|
// Drain the write queue
|
||||||
while (completeQueue.TryDequeue(out var triggerNextCompleted))
|
while (completeQueue.TryDequeue(out var triggerNextCompleted))
|
||||||
{
|
{
|
||||||
|
|
@ -670,7 +696,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests
|
||||||
var frame = new Frame<object>(null, new FrameContext { ServiceContext = serviceContext });
|
var frame = new Frame<object>(null, new FrameContext { ServiceContext = serviceContext });
|
||||||
|
|
||||||
var socket = new MockSocket(_mockLibuv, _libuvThread.Loop.ThreadId, transportContext.Log);
|
var socket = new MockSocket(_mockLibuv, _libuvThread.Loop.ThreadId, transportContext.Log);
|
||||||
var outputProducer = new OutputProducer(pipe.Writer, "0", serviceContext.Log);
|
var outputProducer = new OutputProducer(pipe, "0", serviceContext.Log);
|
||||||
var consumer = new LibuvOutputConsumer(pipe.Reader, _libuvThread, socket, "0", transportContext.Log);
|
var consumer = new LibuvOutputConsumer(pipe.Reader, _libuvThread, socket, "0", transportContext.Log);
|
||||||
frame.Output = outputProducer;
|
frame.Output = outputProducer;
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue