< 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: 12
Uncovered lines: 0
Coverable lines: 12
Total lines: 71
Line coverage: 100%
Branch coverage
100%
Covered branches: 18
Total branches: 18
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%1818100%

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="TypeInitializationException"/>, <see cref="System.Reflection.TargetInvocationExce
 29    /// are unwrapped before classification so that, for example, a <see cref="TypeInitializationException"/>
 30    /// wrapping a <see cref="StackOverflowException"/> is classified as fatal.
 31    /// </para>
 32    /// <para>
 33    /// Pattern: use as a filter on a generic <c>catch</c> where the surrounding logic must remain best-effort
 34    /// for non-fatal errors:
 35    /// <code>
 36    /// try { /* best-effort work */ }
 37    /// catch (Exception ex) when (!ex.IsFatal())
 38    /// {
 39    ///     logger.LogError(ex, "...");
 40    /// }
 41    /// </code>
 42    /// </para>
 43    /// </remarks>
 44    public static bool IsFatal(this Exception? exception)
 45    {
 2546        while (exception is not null)
 47        {
 1648            switch (exception)
 49            {
 50                case StackOverflowException:
 51                case AccessViolationException:
 52                case SEHException:
 53                case ThreadAbortException:
 554                    return true;
 255                case OutOfMemoryException when exception is not InsufficientMemoryException:
 56                    // OOM is fatal, but InsufficientMemoryException (its derived form) is recoverable by design.
 157                    return true;
 58            }
 59
 60            // Unwrap reflection-style wrappers so a fatal cause buried inside a TypeInitializationException is still
 61            // classified as fatal.
 1062            exception = exception switch
 1063            {
 164                TypeInitializationException tie => tie.InnerException,
 165                System.Reflection.TargetInvocationException tie => tie.InnerException,
 866                _ => null,
 1067            };
 68        }
 969        return false;
 70    }
 71}

Methods/Properties

IsFatal(System.Exception)