Skip to content

Commit 0f055ba

Browse files
authored
Split lock to prevent deadlock in Http2Stream. (#47769)
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.
1 parent bde474e commit 0f055ba

File tree

1 file changed

+10
-6
lines changed
  • src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler

1 file changed

+10
-6
lines changed

src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http2Stream.cs

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ private sealed class Http2Stream : IValueTaskSource, IHttpHeadersHandler, IHttpT
3939
private int _pendingWindowUpdate;
4040
private CreditWaiter? _creditWaiter;
4141
private int _availableCredit;
42+
private readonly object _creditSyncObject = new object(); // split from SyncObject to avoid lock ordering problems with Http2Connection.SyncObject
4243

4344
private StreamCompletionState _requestCompletionState;
4445
private StreamCompletionState _responseCompletionState;
@@ -349,11 +350,14 @@ private void Complete()
349350

350351
_connection.RemoveStream(this);
351352

352-
CreditWaiter? w = _creditWaiter;
353-
if (w != null)
353+
lock (_creditSyncObject)
354354
{
355-
w.Dispose();
356-
_creditWaiter = null;
355+
CreditWaiter? waiter = _creditWaiter;
356+
if (waiter != null)
357+
{
358+
waiter.Dispose();
359+
_creditWaiter = null;
360+
}
357361
}
358362
}
359363

@@ -421,7 +425,7 @@ private void Cancel()
421425

422426
public void OnWindowUpdate(int amount)
423427
{
424-
lock (SyncObject)
428+
lock (_creditSyncObject)
425429
{
426430
_availableCredit = checked(_availableCredit + amount);
427431
if (_availableCredit > 0 && _creditWaiter != null)
@@ -1219,7 +1223,7 @@ private async ValueTask SendDataAsync(ReadOnlyMemory<byte> buffer, CancellationT
12191223
while (buffer.Length > 0)
12201224
{
12211225
int sendSize = -1;
1222-
lock (SyncObject)
1226+
lock (_creditSyncObject)
12231227
{
12241228
if (_availableCredit > 0)
12251229
{

0 commit comments

Comments
 (0)