public static void SetupAppDomainHandlers()

in src/common/RunnerCommon.cs [35:129]


        public static void SetupAppDomainHandlers(ILog log, Assembly assemblyToWatch, Action processExitCallback, ManualResetEventSlim shutdownWaitHandle)
        {
            AppDomain.CurrentDomain.UnhandledException += (x, exArgs) =>
            {
                try
                {
                    Exception ex = (Exception)exArgs.ExceptionObject;
                    log.Exception(ex);
                    log.Critical("Unhandled AppDomain exception! {0}: {1}", ex.GetType().ToString(), ex.Message);
                    log.Critical("AppDomain base exception details: {0}: {1}", ex.GetBaseException()?.GetType().ToString(), ex.GetBaseException()?.Message);
                    log.Critical("Is AppDomain terminating? '{0}'", exArgs.IsTerminating.ToString());
                }
                catch (Exception e)
                {
                    Console.Error.WriteLine(e.ToString());
                }
                finally
                {
                    try { log?.Flush(TimeSpan.FromMinutes(1)); } catch { }
                }
            };
            AppDomain.CurrentDomain.DomainUnload += (x, y) =>
            {
                try
                {
                    log.Info("AppDomain unloading");
                }
                catch (Exception e)
                {
                    Console.Error.WriteLine(e.ToString());
                }
                finally
                {
                    try { log?.Flush(TimeSpan.FromMinutes(1)); } catch { }
                }
            };
            int processExitCallbackCalled = 0;
            Console.CancelKeyPress += (x, y) =>
            {
                // This handler gets called when Ctrl+C is pressed
                // Cancel default handling so we have an opportunity to clean up
                y.Cancel = true;
                Task.Delay(TimeSpan.FromSeconds(10)).ContinueWith(t => Environment.Exit((int)Constants.ExitCode.ForceTerminate)).Forget();
                try
                {
                    log.Info("Cancel key pressed. Exiting...");
                    if (Interlocked.Exchange(ref processExitCallbackCalled, 1) == 0)
                    {
                        processExitCallback();
                    }
                }
                catch (Exception e)
                {
                    Console.Error.WriteLine(e.ToString());
                }
            };
            AppDomain.CurrentDomain.ProcessExit += (x, y) =>
            {
                // This handler gets called when the runtime intercepts the SIGTERM signal from Docker.
                // To shutdown gracefully, we must manually tell the webhost to shut down.
                try
                {
                    log.Info("Process exiting...");
                    if (Interlocked.Exchange(ref processExitCallbackCalled, 1) == 0)
                    {
                        processExitCallback();
                    }
                    shutdownWaitHandle.Wait();
                    log.Info("Process exited");
                }
                catch (Exception e)
                {
                    Console.Error.WriteLine(e.ToString());
                }
                finally
                {
                    try { log?.Flush(TimeSpan.FromMinutes(1)); } catch { }
                }
            };
            AssemblyLoadContext.GetLoadContext(assemblyToWatch).Unloading += (x) =>
            {
                try
                {
                    log.Info("AssemblyLoadContext unloading");
                }
                catch (Exception e)
                {
                    Console.Error.WriteLine(e.ToString());
                }
                finally
                {
                    try { log?.Flush(TimeSpan.FromMinutes(1)); } catch { }
                }
            };
        }