Skip to content

Commit ea7f40c

Browse files
committed
Merge pull request #408 from benaadams/CancellationTokenSource
Remove CreateLinkedTokenSource
2 parents 07c0b41 + 16cccb5 commit ea7f40c

File tree

1 file changed

+52
-9
lines changed
  • src/Microsoft.AspNet.Server.Kestrel/Http

1 file changed

+52
-9
lines changed

src/Microsoft.AspNet.Server.Kestrel/Http/Frame.cs

Lines changed: 52 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,8 @@ public partial class Frame : FrameContext, IFrameControl
5353
private Task _requestProcessingTask;
5454
private volatile bool _requestProcessingStopping; // volatile, see: https://msdn.microsoft.com/en-us/library/x13ttww7.aspx
5555
private volatile bool _requestAborted;
56-
private CancellationTokenSource _disconnectCts = new CancellationTokenSource();
57-
private CancellationTokenSource _requestAbortCts;
56+
private CancellationTokenSource _abortedCts;
57+
private CancellationToken? _manuallySetRequestAbortToken;
5858

5959
private FrameRequestStream _requestBody;
6060
private FrameResponseStream _responseBody;
@@ -135,8 +135,47 @@ public string HttpVersion
135135

136136
public Stream DuplexStream { get; set; }
137137

138-
public CancellationToken RequestAborted { get; set; }
138+
public CancellationToken RequestAborted
139+
{
140+
get
141+
{
142+
// If a request abort token was previously explicitly set, return it.
143+
if (_manuallySetRequestAbortToken.HasValue)
144+
return _manuallySetRequestAbortToken.Value;
145+
146+
// Otherwise, get the abort CTS. If we have one, which would mean that someone previously
147+
// asked for the RequestAborted token, simply return its token. If we don't,
148+
// check to see whether we've already aborted, in which case just return an
149+
// already canceled token. Finally, force a source into existence if we still
150+
// don't have one, and return its token.
151+
var cts = _abortedCts;
152+
return
153+
cts != null ? cts.Token :
154+
_requestAborted ? new CancellationToken(true) :
155+
RequestAbortedSource.Token;
156+
}
157+
set
158+
{
159+
// Set an abort token, overriding one we create internally. This setter and associated
160+
// field exist purely to support IHttpRequestLifetimeFeature.set_RequestAborted.
161+
_manuallySetRequestAbortToken = value;
162+
}
163+
}
139164

165+
private CancellationTokenSource RequestAbortedSource
166+
{
167+
get
168+
{
169+
// Get the abort token, lazily-initializing it if necessary.
170+
// Make sure it's canceled if an abort request already came in.
171+
var cts = LazyInitializer.EnsureInitialized(ref _abortedCts, () => new CancellationTokenSource());
172+
if (_requestAborted)
173+
{
174+
cts.Cancel();
175+
}
176+
return cts;
177+
}
178+
}
140179
public bool HasResponseStarted
141180
{
142181
get { return _responseStarted; }
@@ -188,7 +227,8 @@ public void Reset()
188227

189228
_prepareRequest?.Invoke(this);
190229

191-
_requestAbortCts?.Dispose();
230+
_manuallySetRequestAbortToken = null;
231+
_abortedCts = null;
192232
}
193233

194234
public void ResetResponseHeaders()
@@ -244,13 +284,16 @@ public void Abort()
244284
{
245285
ConnectionControl.End(ProduceEndType.SocketDisconnect);
246286
SocketInput.AbortAwaiting();
247-
248-
_disconnectCts.Cancel();
287+
RequestAbortedSource.Cancel();
249288
}
250289
catch (Exception ex)
251290
{
252291
Log.LogError("Abort", ex);
253292
}
293+
finally
294+
{
295+
_abortedCts = null;
296+
}
254297
}
255298

256299
/// <summary>
@@ -294,8 +337,8 @@ public async Task RequestProcessingAsync()
294337
ResponseBody = _responseBody;
295338
DuplexStream = new FrameDuplexStream(RequestBody, ResponseBody);
296339

297-
_requestAbortCts = CancellationTokenSource.CreateLinkedTokenSource(_disconnectCts.Token);
298-
RequestAborted = _requestAbortCts.Token;
340+
_abortedCts = null;
341+
_manuallySetRequestAbortToken = null;
299342

300343
var httpContext = HttpContextFactory.Create(this);
301344
try
@@ -351,7 +394,7 @@ public async Task RequestProcessingAsync()
351394
{
352395
try
353396
{
354-
_disconnectCts.Dispose();
397+
_abortedCts = null;
355398

356399
// If _requestAborted is set, the connection has already been closed.
357400
if (!_requestAborted)

0 commit comments

Comments
 (0)