Skip to content

Commit 79a7156

Browse files
committed
Fix potential crash
1 parent f78ee90 commit 79a7156

File tree

1 file changed

+15
-11
lines changed

1 file changed

+15
-11
lines changed

src/libraries/System.Net.Quic/src/System/Net/Quic/QuicConnection.cs

+15-11
Original file line numberDiff line numberDiff line change
@@ -525,12 +525,12 @@ private unsafe int HandleEventShutdownInitiatedByTransport(ref SHUTDOWN_INITIATE
525525
{
526526
Exception exception = ExceptionDispatchInfo.SetCurrentStackTrace(ThrowHelper.GetExceptionForMsQuicStatus(data.Status, (long)data.ErrorCode));
527527
_connectedTcs.TrySetException(exception);
528-
CompleteAndDrainAcceptQueue(exception);
528+
CompleteAcceptQueue(exception, false);
529529
return QUIC_STATUS_SUCCESS;
530530
}
531531
private unsafe int HandleEventShutdownInitiatedByPeer(ref SHUTDOWN_INITIATED_BY_PEER_DATA data)
532532
{
533-
CompleteAndDrainAcceptQueue(ExceptionDispatchInfo.SetCurrentStackTrace(ThrowHelper.GetConnectionAbortedException((long)data.ErrorCode)));
533+
CompleteAcceptQueue(ExceptionDispatchInfo.SetCurrentStackTrace(ThrowHelper.GetConnectionAbortedException((long)data.ErrorCode)), false);
534534
return QUIC_STATUS_SUCCESS;
535535
}
536536
private unsafe int HandleEventShutdownComplete()
@@ -539,7 +539,7 @@ private unsafe int HandleEventShutdownComplete()
539539
_tlsSecret?.WriteSecret();
540540

541541
Exception exception = ExceptionDispatchInfo.SetCurrentStackTrace(_disposed == 1 ? new ObjectDisposedException(GetType().FullName) : ThrowHelper.GetOperationAbortedException());
542-
CompleteAndDrainAcceptQueue(exception);
542+
CompleteAcceptQueue(exception, true);
543543
_connectedTcs.TrySetException(exception);
544544
_shutdownTokenSource.Cancel();
545545
_shutdownTcs.TrySetResult(final: true);
@@ -643,22 +643,26 @@ private static unsafe int NativeCallback(QUIC_HANDLE* connection, void* context,
643643
}
644644
}
645645

646-
private void CompleteAndDrainAcceptQueue(Exception? ex)
646+
private void CompleteAcceptQueue(Exception? ex, bool drain)
647647
{
648-
if (_acceptQueue.Writer.TryComplete(ex))
648+
_acceptQueue.Writer.TryComplete(ex);
649+
650+
if (drain)
649651
{
650-
// also drain the queue. Because stream shutdown events are indicated before connection shutdown,
651-
// the QuicStream instances have already been signaled and closed internally. We only need to dispose them,
652-
// which in this situation should complete synchronously.
652+
// This should be only called after connection SHUTDOWN_COMPLETE has been indicated.
653+
// At that point, all streams have been already shut down internally and we need
654+
// only to close the handle via dispose, so DisposeAsync below should complete
655+
// synchronously (which is necessary for this method to be callable from MsQuic
656+
// event callback).
653657
while (_acceptQueue.Reader.TryRead(out QuicStream? stream))
654658
{
655659
ValueTask task = stream.DisposeAsync();
656660
Debug.Assert(task.IsCompletedSuccessfully);
657661
task.GetAwaiter().GetResult();
658662
}
659-
}
660663

661-
Debug.Assert(_acceptQueue.Reader.Completion.IsCompleted);
664+
Debug.Assert(_acceptQueue.Reader.Completion.IsCompleted);
665+
}
662666
}
663667

664668
/// <summary>
@@ -709,6 +713,6 @@ public async ValueTask DisposeAsync()
709713
}
710714

711715
// Flush the queue and dispose all remaining streams.
712-
CompleteAndDrainAcceptQueue(ExceptionDispatchInfo.SetCurrentStackTrace(new ObjectDisposedException(GetType().FullName)));
716+
CompleteAcceptQueue(ExceptionDispatchInfo.SetCurrentStackTrace(new ObjectDisposedException(GetType().FullName)), true);
713717
}
714718
}

0 commit comments

Comments
 (0)