How to terminate .NET application on a specific exception - possibly without stack unwinding?

送分小仙女□ 提交于 2019-12-13 02:24:29

问题


I have a .NET application (service) that consists of C# and C++ code.

"Crashes" (i.e. System.AccessViolationException and other Corrupted State Exceptions) in the C++ Code will be ("non-") handled correctly, they will directly lead to my AppDomain.CurrentDomain.UnhandledException handler (which logs) and then the application will terminate, writing a WER dump file if so configured (which it is).

For this application, I have determined that System.NullReferenceException is always a bug, especially since some C++/CLI Access Violation bugs will report this one instead of an AV.

Is there any way to make .NET not catch a NullReferenceException on an exception boundary (my OnTimer callback in this case) but instead directly terminate the app, without unwinding the stack, basically "jumping" directly to AppDomain.CurrentDomain.UnhandledException?


回答1:


You could:

AppDomain.CurrentDomain.FirstChanceException += CurrentDomain_FirstChanceException;

and then

static void CurrentDomain_FirstChanceException(object sender, FirstChanceExceptionEventArgs e)
{
    if (e.Exception is NullReferenceException)
    {
        Environment.FailFast("FailFast", e.Exception);
    }
}

The Environment.FailFast:

Immediately terminates a process after writing a message to the Windows Application event log, and then includes the message in error reporting to Microsoft.

and

This method terminates a process without running any active try/finally blocks or finalizers.

Clearly in the CurrentDomain_FirstChanceException you could duplicate the logging code you probably have in your UnhandledException (or have a common method that is called by both)




回答2:


The fact that FirstChanceException is actually a "simple" global exception filter got me on the track (it remains to be seen whether it's the "right" track):

We already have exception filters in CLI.

If one has the luxury of working in C# 6, it's as simple as:

        try
        {
            throw new NullReferenceException("No, Really");
        }
        catch(Exception ex) when (FilterExType(ex))
        {
            Console.WriteLine($"2: Caught 'any' exception: {ex}");
        }

    static bool FilterExType(Exception ex)
    {
        if (ex is NullReferenceException)
        {
            Environment.FailFast("BOOM from C#!", ex);
        }
        // always handle if we return
        return true;
    }

And for those of us (like me) stuck on earlier versions, we can route the filtering through VB.NET via a delegate / lambda:

        try {
            VbFilterLib.FilteredRunner.RunFiltered(() =>
            {
                throw new NullReferenceException("Via VB.NET");
            });
        } 
        catch (Exception ex)
        {
            Console.WriteLine("1: Caught 'any' exception: {0}", ex");
        }

with VB as such (bear with me, VB.NET is far from a language I'm fluent in):

Public Class FilteredRunner
    Delegate Sub VoidCode()

    Private Shared Function FilterAction(x As Exception) As Boolean
        If TypeOf x Is NullReferenceException Then
            Environment.FailFast("Abort program! Investigate Bug via crash dump!", x)
        End If
        ' Never handle here:'
        Return False
    End Function

    Public Shared Sub RunFiltered(code As VoidCode)
        Try
            code.Invoke()
        Catch ex As Exception When FilterAction(ex)
            Throw New InvalidProgramException("Unreachable!", ex)
        End Try
    End Sub

End Class

Obviously, to make it work you need some more configuration rigging, but that seems to be exactly what I want. :-)



来源:https://stackoverflow.com/questions/35503673/how-to-terminate-net-application-on-a-specific-exception-possibly-without-sta

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!