diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/Internal/ThrowHelper.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/Internal/ThrowHelper.cs index fa86818619f75c..774d0f71398f4d 100644 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/Internal/ThrowHelper.cs +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/Internal/ThrowHelper.cs @@ -215,26 +215,4 @@ public static void ValidateNotNull(string argumentName, string resourceName, obj throw new ArgumentNullException(argumentName, SR.Format(resourceName, propertyName)); } } - - public static void ObserveException(this Task task) - { - if (task.IsCompleted) - { - ObserveExceptionCore(task); - } - else - { - task.ContinueWith(static (t) => ObserveExceptionCore(t), CancellationToken.None, TaskContinuationOptions.ExecuteSynchronously | TaskContinuationOptions.OnlyOnFaulted, TaskScheduler.Default); - } - - static void ObserveExceptionCore(Task task) - { - Debug.Assert(task.IsCompleted); - if (task.IsFaulted) - { - // Access Exception to avoid TaskScheduler.UnobservedTaskException firing. - Exception? e = task.Exception!.InnerException; - } - } - } } diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicConnection.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicConnection.cs index 95457e48584077..63be64f12af7f8 100644 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicConnection.cs +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicConnection.cs @@ -658,14 +658,22 @@ private unsafe int HandleEventShutdownInitiatedByTransport(ref SHUTDOWN_INITIATE { Exception exception = ExceptionDispatchInfo.SetCurrentStackTrace(ThrowHelper.GetExceptionForMsQuicStatus(data.Status, (long)data.ErrorCode)); _connectedTcs.TrySetException(exception); - _connectionCloseTcs.TrySetException(exception); + if (_connectionCloseTcs.TrySetException(exception)) + { + // Observe the exception as the task is used only for internal workings and might not be observed. + _ = _connectionCloseTcs.Task.Exception; + } _acceptQueue.Writer.TryComplete(exception); return QUIC_STATUS_SUCCESS; } private unsafe int HandleEventShutdownInitiatedByPeer(ref SHUTDOWN_INITIATED_BY_PEER_DATA data) { Exception exception = ExceptionDispatchInfo.SetCurrentStackTrace(ThrowHelper.GetConnectionAbortedException((long)data.ErrorCode)); - _connectionCloseTcs.TrySetException(exception); + if (_connectionCloseTcs.TrySetException(exception)) + { + // Observe the exception as the task is used only for internal workings and might not be observed. + _ = _connectionCloseTcs.Task.Exception; + } _acceptQueue.Writer.TryComplete(exception); return QUIC_STATUS_SUCCESS; } @@ -675,7 +683,11 @@ private unsafe int HandleEventShutdownComplete() _tlsSecret?.WriteSecret(); Exception exception = ExceptionDispatchInfo.SetCurrentStackTrace(_disposed ? new ObjectDisposedException(GetType().FullName) : ThrowHelper.GetOperationAbortedException()); - _connectionCloseTcs.TrySetException(exception); + if (_connectionCloseTcs.TrySetException(exception)) + { + // Observe the exception as the task is used only for internal workings and might not be observed. + _ = _connectionCloseTcs.Task.Exception; + } _acceptQueue.Writer.TryComplete(exception); _connectedTcs.TrySetException(exception); _shutdownTokenSource.Cancel(); @@ -850,7 +862,6 @@ public async ValueTask DisposeAsync() Debug.Assert(_connectionCloseTcs.Task.IsCompleted); _handle.Dispose(); _shutdownTokenSource.Dispose(); - _connectionCloseTcs.Task.ObserveException(); _configuration?.Dispose(); // Dispose remote certificate only if it hasn't been accessed via getter, in which case the accessing code becomes the owner of the certificate lifetime.