< Summary

Information
Class: Elsa.Common.ExceptionExtensions
Assembly: Elsa.Common
File(s): /home/runner/work/elsa-core/elsa-core/src/modules/Elsa.Common/Extensions/ExceptionExtensions.cs
Line coverage
100%
Covered lines: 14
Uncovered lines: 0
Coverable lines: 14
Total lines: 75
Line coverage: 100%
Branch coverage
100%
Covered branches: 20
Total branches: 20
Branch coverage: 100%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
IsFatal(...)100%2020100%

File(s)

/home/runner/work/elsa-core/elsa-core/src/modules/Elsa.Common/Extensions/ExceptionExtensions.cs

#LineLine coverage
 1using System.Runtime.InteropServices;
 2
 3namespace Elsa.Common;
 4
 5/// <summary>
 6/// Helpers for classifying exceptions during best-effort error handling.
 7/// </summary>
 8public static class ExceptionExtensions
 9{
 10    /// <summary>
 11    /// Returns <c>true</c> when <paramref name="exception"/> represents a process-fatal condition that should
 12    /// NOT be swallowed even by best-effort code paths. Catches that filter on <c>!ex.IsFatal()</c> let normal
 13    /// failures through for logging-and-continue while letting fatal exceptions propagate to crash the process
 14    /// cleanly (the host's failure-fast policy can then decide what to do).
 15    /// </summary>
 16    /// <remarks>
 17    /// <para>
 18    /// Conditions classified as fatal:
 19    /// </para>
 20    /// <list type="bullet">
 21    ///   <item><see cref="OutOfMemoryException"/> (when not <see cref="InsufficientMemoryException"/>, which is recover
 22    ///   <item><see cref="StackOverflowException"/></item>
 23    ///   <item><see cref="AccessViolationException"/></item>
 24    ///   <item><see cref="SEHException"/></item>
 25    ///   <item><see cref="ThreadAbortException"/></item>
 26    /// </list>
 27    /// <para>
 28    /// Wrapper exceptions (<see cref="AggregateException"/>, <see cref="TypeInitializationException"/>,
 29    /// <see cref="System.Reflection.TargetInvocationException"/>) are unwrapped before classification so that,
 30    /// for example, an aggregate or <see cref="TypeInitializationException"/> wrapping a
 31    /// <see cref="StackOverflowException"/> is classified as fatal.
 32    /// </para>
 33    /// <para>
 34    /// Pattern: use as a filter on a generic <c>catch</c> where the surrounding logic must remain best-effort
 35    /// for non-fatal errors:
 36    /// <code>
 37    /// try { /* best-effort work */ }
 38    /// catch (Exception ex) when (!ex.IsFatal())
 39    /// {
 40    ///     logger.LogError(ex, "...");
 41    /// }
 42    /// </code>
 43    /// </para>
 44    /// </remarks>
 45    public static bool IsFatal(this Exception? exception)
 46    {
 3447        while (exception is not null)
 48        {
 2249            if (exception is AggregateException aggregateException)
 650                return aggregateException.Flatten().InnerExceptions.Any(inner => inner.IsFatal());
 51
 2052            switch (exception)
 53            {
 54                case StackOverflowException:
 55                case AccessViolationException:
 56                case SEHException:
 57                case ThreadAbortException:
 558                    return true;
 359                case OutOfMemoryException when exception is not InsufficientMemoryException:
 60                    // OOM is fatal, but InsufficientMemoryException (its derived form) is recoverable by design.
 261                    return true;
 62            }
 63
 64            // Unwrap reflection-style wrappers so a fatal cause buried inside a TypeInitializationException is still
 65            // classified as fatal.
 1366            exception = exception switch
 1367            {
 168                TypeInitializationException tie => tie.InnerException,
 169                System.Reflection.TargetInvocationException tie => tie.InnerException,
 1170                _ => null,
 1371            };
 72        }
 1273        return false;
 74    }
 75}

Methods/Properties

IsFatal(System.Exception)