Skip to content

Commit

Permalink
Split lock to prevent deadlock between OnWindowsUpdate and Complete.
Browse files Browse the repository at this point in the history
Http2Connection.ChangeInitialWindowSize locks connection's SyncObject and calls Http2Stream.OnWindowUpdate which locks stream's SyncObject.
Http2Stream.Complete is called only while stream's SyncObject lock is take and then it calls Http2Connection.RemoveStream that locks connection SyncObject.
  • Loading branch information
ManickaP committed Feb 2, 2021
1 parent 20e2242 commit d68a2d4
Showing 1 changed file with 10 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ private sealed class Http2Stream : IValueTaskSource, IHttpHeadersHandler, IHttpT
private int _pendingWindowUpdate;
private CreditWaiter? _creditWaiter;
private int _availableCredit;
private readonly object _creditSyncObject = new object(); // split from SyncObject to mitigate deadlock in OnWindowUpdate.

private StreamCompletionState _requestCompletionState;
private StreamCompletionState _responseCompletionState;
Expand Down Expand Up @@ -349,11 +350,14 @@ private void Complete()

_connection.RemoveStream(this);

CreditWaiter? w = _creditWaiter;
if (w != null)
lock (_creditSyncObject)
{
w.Dispose();
_creditWaiter = null;
CreditWaiter? waiter = _creditWaiter;
if (waiter != null)
{
waiter.Dispose();
_creditWaiter = null;
}
}
}

Expand Down Expand Up @@ -421,7 +425,7 @@ private void Cancel()

public void OnWindowUpdate(int amount)
{
lock (SyncObject)
lock (_creditSyncObject)
{
_availableCredit = checked(_availableCredit + amount);
if (_availableCredit > 0 && _creditWaiter != null)
Expand Down Expand Up @@ -1219,7 +1223,7 @@ private async ValueTask SendDataAsync(ReadOnlyMemory<byte> buffer, CancellationT
while (buffer.Length > 0)
{
int sendSize = -1;
lock (SyncObject)
lock (_creditSyncObject)
{
if (_availableCredit > 0)
{
Expand Down

0 comments on commit d68a2d4

Please sign in to comment.