AppDomain.FirstChanceException and stack overflow exception

前端 未结 7 1690

I\'m using the FirstChanceException event to log details about any thrown exceptions.

static void Main(string[] args)
{
    AppDomain.CurrentDomain.FirstChanceEx         


        
相关标签:
7条回答
  • 2021-02-05 11:16

    First use a method instead of a delegate, so the method name will be defined

    Then use Environment.StackTrace to check if the method is already in the stacktrace

    Here is a piece of code untested:

    static void Main(string[] args) 
    { 
        AppDomain.CurrentDomain.FirstChanceException += handleFirstChanceException;
    } 
    
    private void handleFirstChanceException(object sender, EventArgs eventArgs)
    {
        if (Environment.StackTrace.Contains("handleFirstChanceException"))
            return;
    
        // handle
    }
    

    I think the above will not work because it'll always contains the method name, but you can count if it appear more than 1 time. Also, check that it's not inlined when you compile in Release mode, in this case you're in trouble

    0 讨论(0)
  • 2021-02-05 11:17

    The MSDN article you linked makes a few recommandations:

    You must handle all exceptions that occur in the event handler for the FirstChanceException event. Otherwise, FirstChanceException is raised recursively. This could result in a stack overflow and termination of the application. We recommend that you implement event handlers for this event as constrained execution regions (CERs), to keep infrastructure-related exceptions such as out-of-memory or stack overflow from affecting the virtual machine while the exception notification is being processed.

    So enclose your function inside a try/catch block, and call PrepareConstrainedRegion before the block to avoid OutOfMemory exceptions: http://msdn.microsoft.com/en-us/library/system.runtime.compilerservices.runtimehelpers.prepareconstrainedregions.aspx

    Edit: Well, you still have the recursion issue even with the try/catch block. So... I guess you just have to call only safe code that won't throw any exception. That event handler seems quite dangerous, I'd recommend to use it only for debugging purpose.

    0 讨论(0)
  • 2021-02-05 11:20

    I think adding another try {} catch (){} block in the exception handler would help

    static void Main(string[] args) 
    { 
        AppDomain.CurrentDomain.FirstChanceException += (sender, eventArgs) => 
        { 
            try {
                throw new Exception("Stackoverflow"); 
            } catch (Exception e)
            {
               // Do something very simple not throwing an exception...
            }
        }; 
    
        throw new Exception("Exception thrown in main."); 
    } 
    
    0 讨论(0)
  • 2021-02-05 11:25

    This is working for me:

    private volatile bool _insideFirstChanceExceptionHandler;    
    
    // ...
    
    AppDomain.CurrentDomain.FirstChanceException += OnFirstChanceException;
    
    // ...
    
    private void OnFirstChanceException(object sender, FirstChanceExceptionEventArgs args)
    {
        if (_insideFirstChanceExceptionHandler)
        {
            // Prevent recursion if an exception is thrown inside this method
            return;
        }
    
        _insideFirstChanceExceptionHandler = true;
        try
        {
            // Code which may throw an exception
        }
        catch
        {
            // You have to catch all exceptions inside this method
        }
        finally
        {
            _insideFirstChanceExceptionHandler = false;
        }
    }
    
    0 讨论(0)
  • 2021-02-05 11:25

    Eventhough it is not a good way, in VB .NET you can prevent exception firing inside FirstChanceException event handler using "On Error Resume Next" statement, coming from VB 6. (I am not sure if C# has something similar) Additionally, you should prevent recursion on the event handler as mentioned here. Following is the sample code, seems to work as expected.

    Sub Main(args As String())
        AddHandler AppDomain.CurrentDomain.FirstChanceException, AddressOf FirstChanceExceptionEventHandler
        Throw New Exception("Exception thrown in main.")
    End Sub
    
    Private Sub FirstChanceExceptionEventHandler(ByVal source As Object, ByVal e As FirstChanceExceptionEventArgs)
        On Error Resume Next
    
        Dim frames As StackFrame() = New StackTrace(1).GetFrames()
        Dim currentMethod As MethodBase = MethodBase.GetCurrentMethod()
        If frames IsNot Nothing AndAlso frames.Any(Function(x) x.GetMethod() = currentMethod) Then
            Return
        Else
            Throw New Exception("Stackoverflow")
        End If
    End Sub
    
    0 讨论(0)
  • 2021-02-05 11:29

    In general exception you can handle like all others, but what about in particular StackOverflow and OutOfMemory exception, they can not be handled in .NET Framework.

    Look here: How do I prevent and/or handle a StackOverflowException? (C#)

    Starting with the .NET Framework version 2.0, a StackOverflowException object cannot be caught by a try-catch block and the corresponding process is terminated by default. Consequently, users are advised to write their code to detect and prevent a stack overflow. For example, if your application depends on recursion, use a counter or a state condition to terminate the recursive loop.

    0 讨论(0)
提交回复
热议问题