Merge pull request #408 from benaadams/CancellationTokenSource

Remove CreateLinkedTokenSource
This commit is contained in:
David Fowler 2015-11-25 01:32:04 -08:00
commit ea7f40c592
1 changed files with 52 additions and 9 deletions

View File

@ -53,8 +53,8 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
private Task _requestProcessingTask; private Task _requestProcessingTask;
private volatile bool _requestProcessingStopping; // volatile, see: https://msdn.microsoft.com/en-us/library/x13ttww7.aspx private volatile bool _requestProcessingStopping; // volatile, see: https://msdn.microsoft.com/en-us/library/x13ttww7.aspx
private volatile bool _requestAborted; private volatile bool _requestAborted;
private CancellationTokenSource _disconnectCts = new CancellationTokenSource(); private CancellationTokenSource _abortedCts;
private CancellationTokenSource _requestAbortCts; private CancellationToken? _manuallySetRequestAbortToken;
private FrameRequestStream _requestBody; private FrameRequestStream _requestBody;
private FrameResponseStream _responseBody; private FrameResponseStream _responseBody;
@ -135,8 +135,47 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
public Stream DuplexStream { get; set; } public Stream DuplexStream { get; set; }
public CancellationToken RequestAborted { get; set; } public CancellationToken RequestAborted
{
get
{
// If a request abort token was previously explicitly set, return it.
if (_manuallySetRequestAbortToken.HasValue)
return _manuallySetRequestAbortToken.Value;
// Otherwise, get the abort CTS. If we have one, which would mean that someone previously
// asked for the RequestAborted token, simply return its token. If we don't,
// check to see whether we've already aborted, in which case just return an
// already canceled token. Finally, force a source into existence if we still
// don't have one, and return its token.
var cts = _abortedCts;
return
cts != null ? cts.Token :
_requestAborted ? new CancellationToken(true) :
RequestAbortedSource.Token;
}
set
{
// Set an abort token, overriding one we create internally. This setter and associated
// field exist purely to support IHttpRequestLifetimeFeature.set_RequestAborted.
_manuallySetRequestAbortToken = value;
}
}
private CancellationTokenSource RequestAbortedSource
{
get
{
// Get the abort token, lazily-initializing it if necessary.
// Make sure it's canceled if an abort request already came in.
var cts = LazyInitializer.EnsureInitialized(ref _abortedCts, () => new CancellationTokenSource());
if (_requestAborted)
{
cts.Cancel();
}
return cts;
}
}
public bool HasResponseStarted public bool HasResponseStarted
{ {
get { return _responseStarted; } get { return _responseStarted; }
@ -188,7 +227,8 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
_prepareRequest?.Invoke(this); _prepareRequest?.Invoke(this);
_requestAbortCts?.Dispose(); _manuallySetRequestAbortToken = null;
_abortedCts = null;
} }
public void ResetResponseHeaders() public void ResetResponseHeaders()
@ -244,13 +284,16 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
{ {
ConnectionControl.End(ProduceEndType.SocketDisconnect); ConnectionControl.End(ProduceEndType.SocketDisconnect);
SocketInput.AbortAwaiting(); SocketInput.AbortAwaiting();
RequestAbortedSource.Cancel();
_disconnectCts.Cancel();
} }
catch (Exception ex) catch (Exception ex)
{ {
Log.LogError("Abort", ex); Log.LogError("Abort", ex);
} }
finally
{
_abortedCts = null;
}
} }
/// <summary> /// <summary>
@ -294,8 +337,8 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
ResponseBody = _responseBody; ResponseBody = _responseBody;
DuplexStream = new FrameDuplexStream(RequestBody, ResponseBody); DuplexStream = new FrameDuplexStream(RequestBody, ResponseBody);
_requestAbortCts = CancellationTokenSource.CreateLinkedTokenSource(_disconnectCts.Token); _abortedCts = null;
RequestAborted = _requestAbortCts.Token; _manuallySetRequestAbortToken = null;
var httpContext = HttpContextFactory.Create(this); var httpContext = HttpContextFactory.Create(this);
try try
@ -351,7 +394,7 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
{ {
try try
{ {
_disconnectCts.Dispose(); _abortedCts = null;
// If _requestAborted is set, the connection has already been closed. // If _requestAborted is set, the connection has already been closed.
if (!_requestAborted) if (!_requestAborted)