File: src\libraries\System.Private.CoreLib\src\System\Runtime\ExceptionServices\ExceptionHandling.cs
Web Access
Project: src\src\coreclr\System.Private.CoreLib\System.Private.CoreLib.csproj (System.Private.CoreLib)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using System.Threading;
 
namespace System.Runtime.ExceptionServices
{
    /// <summary>
    /// Provides helpers for configuring and raising global unhandled exception handlers.
    /// </summary>
    public static class ExceptionHandling
    {
        private static Func<Exception, bool>? s_handler;
 
        internal static bool IsHandledByGlobalHandler(Exception ex)
        {
            return s_handler?.Invoke(ex) == true;
        }
 
        /// <summary>
        /// Sets a handler for unhandled exceptions.
        /// </summary>
        /// <param name="handler">A callback that will be invoked for unhandled exceptions. Return <see langword="true"/> if the exception was handled; otherwise <see langword="false"/>.</param>
        /// <exception cref="ArgumentNullException"><paramref name="handler" /> is null.</exception>
        /// <exception cref="InvalidOperationException">A handler is already set.</exception>
        /// <remarks>
        /// The handler is called when an unhandled exception occurs.
        /// The handler should return <see langword="true" /> if the exception was handled, or <see langword="false" /> if it was not.
        /// If the handler returns false, the exception will continue to propagate as unhandled.
        ///
        /// The intent of this handler is to allow the user to handle unhandled exceptions
        /// gracefully when the runtime is being used in certain scenarios. Scenarios such
        /// as REPLs or game scripting that host plug-ins are not able to handle unhandled
        /// exceptions thrown by those plug-ins.
        /// </remarks>
        public static void SetUnhandledExceptionHandler(Func<Exception, bool> handler)
        {
            ArgumentNullException.ThrowIfNull(handler);
 
            if (Interlocked.CompareExchange(ref s_handler, handler, null) != null)
            {
                throw new InvalidOperationException(SR.InvalidOperation_CannotRegisterSecondHandler);
            }
        }
 
        /// <summary>
        /// Raises the <see cref="AppDomain.UnhandledException"/> event.
        /// </summary>
        /// <param name="exception">Exception to pass to event handlers.</param>
        /// <remarks>
        /// This method will raise the <see cref="AppDomain.UnhandledException"/>
        /// event and then return.
        ///
        /// It will not raise the the handler registered with <see cref="SetUnhandledExceptionHandler"/>.
        ///
        /// This API is thread safe and can be called from multiple threads. However, only one thread
        /// will trigger the event handlers, while other threads will wait indefinitely without raising
        /// the event.
        /// </remarks>
        public static void RaiseAppDomainUnhandledExceptionEvent(object exception)
        {
            ArgumentNullException.ThrowIfNull(exception);
 
            AppContext.OnUnhandledException(exception);
        }
    }
}