Added FrameConnection.OnConnectionClosed back (#2028)

This commit is contained in:
David Fowler 2017-08-26 21:20:06 -07:00 committed by GitHub
parent 7854c0604a
commit 9d8556e7c4
2 changed files with 36 additions and 15 deletions

View File

@ -28,6 +28,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal
private readonly FrameConnectionContext _context; private readonly FrameConnectionContext _context;
private IList<IAdaptedConnection> _adaptedConnections; private IList<IAdaptedConnection> _adaptedConnections;
private readonly TaskCompletionSource<object> _socketClosedTcs = new TaskCompletionSource<object>(TaskCreationOptions.RunContinuationsAsynchronously);
private Frame _frame; private Frame _frame;
private Http2Connection _http2Connection; private Http2Connection _http2Connection;
private volatile int _http2ConnectionState; private volatile int _http2ConnectionState;
@ -151,6 +152,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal
} }
await adaptedPipelineTask; await adaptedPipelineTask;
await _socketClosedTcs.Task;
} }
catch (Exception ex) catch (Exception ex)
{ {
@ -189,6 +191,13 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal
}); });
} }
public void OnConnectionClosed(Exception ex)
{
Abort(ex);
_socketClosedTcs.TrySetResult(null);
}
public Task StopAsync() public Task StopAsync()
{ {
Debug.Assert(_frame != null, $"{nameof(_frame)} is null"); Debug.Assert(_frame != null, $"{nameof(_frame)} is null");

View File

@ -13,6 +13,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal
{ {
public class HttpConnectionMiddleware<TContext> public class HttpConnectionMiddleware<TContext>
{ {
private static Action<Exception, object> _completeTcs = CompleteTcs;
private static long _lastFrameConnectionId = long.MinValue; private static long _lastFrameConnectionId = long.MinValue;
private readonly IList<IConnectionAdapter> _connectionAdapters; private readonly IList<IConnectionAdapter> _connectionAdapters;
@ -67,22 +69,12 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal
var processingTask = connection.StartRequestProcessing(_application); var processingTask = connection.StartRequestProcessing(_application);
var inputTcs = new TaskCompletionSource<object>(); var inputTcs = new TaskCompletionSource<object>();
var outputTcs = new TaskCompletionSource<object>();
// Abort the frame when the transport writer completes // The reason we don't fire events directly from these callbacks is because it seems
connectionContext.Transport.Input.OnWriterCompleted((error, state) => // like the transport callbacks root the state object (even after it fires)
{ connectionContext.Transport.Input.OnWriterCompleted(_completeTcs, inputTcs);
var tcs = (TaskCompletionSource<object>)state; connectionContext.Transport.Output.OnReaderCompleted(_completeTcs, outputTcs);
if (error != null)
{
tcs.TrySetException(error);
}
else
{
tcs.TrySetResult(null);
}
},
inputTcs);
inputTcs.Task.ContinueWith((task, state) => inputTcs.Task.ContinueWith((task, state) =>
{ {
@ -90,7 +82,27 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal
}, },
connection, TaskContinuationOptions.ExecuteSynchronously); connection, TaskContinuationOptions.ExecuteSynchronously);
outputTcs.Task.ContinueWith((task, state) =>
{
((FrameConnection)state).OnConnectionClosed(task.Exception?.InnerException);
},
connection, TaskContinuationOptions.ExecuteSynchronously);
return processingTask; return processingTask;
} }
private static void CompleteTcs(Exception error, object state)
{
var tcs = (TaskCompletionSource<object>)state;
if (error != null)
{
tcs.TrySetException(error);
}
else
{
tcs.TrySetResult(null);
}
}
} }
} }