Skip to content

Commit cebb459

Browse files
committed
better
1 parent 331725a commit cebb459

File tree

2 files changed

+42
-16
lines changed

2 files changed

+42
-16
lines changed

src/Servers/Kestrel/Core/src/Internal/Http2/Http2FrameWriter.cs

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -370,17 +370,31 @@ public void UpdateMaxFrameSize(uint maxFrameSize)
370370
}
371371
}
372372

373+
/// <summary>
374+
/// Call while in the <c>_writeLock</c>.
375+
/// </summary>
376+
/// <returns><c>true</c> if already completed.</returns>
377+
private bool CompleteUnsynchronized()
378+
{
379+
if (_completed)
380+
{
381+
return true;
382+
}
383+
384+
_completed = true;
385+
_outputWriter.Abort();
386+
387+
return false;
388+
}
389+
373390
public void Complete()
374391
{
375392
lock (_writeLock)
376393
{
377-
if (_completed)
394+
if (CompleteUnsynchronized())
378395
{
379396
return;
380397
}
381-
382-
_completed = true;
383-
_outputWriter.Abort();
384398
}
385399

386400
// Ok to call after aborting the Pipe because we've already set _completed to true which means any writes from the abort call
@@ -407,7 +421,10 @@ public void Abort(ConnectionAbortedException error)
407421
_aborted = true;
408422
_connectionContext.Abort(error);
409423

410-
Complete();
424+
if (CompleteUnsynchronized())
425+
{
426+
return;
427+
}
411428
}
412429
}
413430

src/Servers/Kestrel/Core/src/Internal/Http2/Http2OutputProducer.cs

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -590,6 +590,7 @@ public void Reset()
590590

591591
internal void OnRequestProcessingEnded()
592592
{
593+
var shouldCompleteStream = false;
593594
lock (_dataWriterLock)
594595
{
595596
if (_requestProcessingComplete)
@@ -600,15 +601,22 @@ internal void OnRequestProcessingEnded()
600601

601602
_requestProcessingComplete = true;
602603

603-
if (_completedResponse)
604-
{
605-
Stream.CompleteStream(errored: false);
606-
}
604+
shouldCompleteStream = _completedResponse;
605+
}
606+
607+
// Complete outside of lock, anything this method does that needs a lock will acquire a lock itself.
608+
if (shouldCompleteStream)
609+
{
610+
Stream.CompleteStream(errored: false);
607611
}
612+
608613
}
609614

610615
internal ValueTask<FlushResult> CompleteResponseAsync()
611616
{
617+
var shouldCompleteStream = false;
618+
ValueTask<FlushResult> task = default;
619+
612620
lock (_dataWriterLock)
613621
{
614622
if (_completedResponse)
@@ -619,22 +627,23 @@ internal ValueTask<FlushResult> CompleteResponseAsync()
619627

620628
_completedResponse = true;
621629

622-
ValueTask<FlushResult> task = default;
623-
624630
if (_resetErrorCode is { } error)
625631
{
626632
// If we have an error code to write, write it now that we're done with the response.
627633
// Always send the reset even if the response body is completed. The request body may not have completed yet.
628634
task = _frameWriter.WriteRstStreamAsync(StreamId, error);
629635
}
630636

631-
if (_requestProcessingComplete)
632-
{
633-
Stream.CompleteStream(errored: false);
634-
}
637+
shouldCompleteStream = _requestProcessingComplete;
638+
}
635639

636-
return task;
640+
// Complete outside of lock, anything this method does that needs a lock will acquire a lock itself.
641+
if (shouldCompleteStream)
642+
{
643+
Stream.CompleteStream(errored: false);
637644
}
645+
646+
return task;
638647
}
639648

640649
internal Memory<byte> GetFakeMemory(int minSize)

0 commit comments

Comments
 (0)