What actions do I need to take to get a crash dump in ALL error scenarios?

前端 未结 6 1123
孤独总比滥情好
孤独总比滥情好 2021-02-04 09:39

We\'re on Windows and we want to get a crash dump (possibly using MiniDumpWriteDump) for all scenarios where our application exit\'s unexpectedly.

6条回答
  •  甜味超标
    2021-02-04 10:07

    To expand on all the answers here's what I found to work best for 100M+ installs:

    • SetErrorMode to prevent any WER dialogs showing up.
    • EnableCrashingOnCrashes
    • PreventSetUnhandledExceptionFilter
    • SetUnhandledExceptionFilter for system exceptions.
    • _set_invalid_parameter_handler for the CRT invalid argument handling
    • _set_abort_behavior plus a SIGABRT handler to account for calls to abort()

    std::set_terminate and std::set_unexpected perhaps should also be mentioned.

    And the most important part to get it all right:

    • all these handlers should call a function that executes under a mutex/critical section to ensure that if there are any other crashes happening in other threads at the same time they would all stop and wait instead of causing havoc.
    • signal handler for SIGABRT must set itself back as a SIGABRT handler! Without this if you get crashes happening at the same time from other threads you process will exit immediately without giving you any time to handle the crash.
    • actual handling of the error should ideally happen in another process, or at least in another thread that was started at the beginning of the process, otherwise you won't be able to handle low memory conditions or stackoverflow errors.

    See setExceptionHandlers below for reference. Also, most likely you don't want to hook up all the handlers in debug builds or when IsDebuggerPresent.

    #include 
    #include 
    #include 
    
    void EnableCrashingOnCrashes();
    void PreventSetUnhandledExceptionFilter();
    
    static void exceptionHandler(EXCEPTION_POINTERS* excpInfo)
    {
        // your code to handle the exception. Ideally it should
        // marshal the exception for processing to some other
        // thread and waif for the thread to complete the job
    }
    
    static boost::mutex unhandledExceptionMx;
    static LONG WINAPI unhandledException(EXCEPTION_POINTERS* excpInfo = NULL)
    {
        boost::mutex::scoped_lock lock(unhandledExceptionMx);
        if (!excpInfo == NULL)
        {
            __try // Generate exception to get proper context in dump
            {
                RaiseException(EXCEPTION_BREAKPOINT, 0, 0, NULL);
            }
            __except (exceptionHandler(GetExceptionInformation()), EXCEPTION_EXECUTE_HANDLER)
            {
            }
        }
        else
        {
            exceptionHandler(excpInfo);
        }
    
        return 0;
    }
    
    static void invalidParameter(const wchar_t* expr, const wchar_t* func,
        const wchar_t* file, unsigned int line, uintptr_t reserved)
    {
        unhandledException();
    }
    
    static void pureVirtualCall()
    {
        unhandledException();
    }
    
    static void sigAbortHandler(int sig)
    {
        // this is required, otherwise if there is another thread
        // simultaneously tries to abort process will be terminated
        signal(SIGABRT, sigAbortHandler);
        unhandledException();
    }
    
    static void setExceptionHandlers()
    {
        SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX);
        SetUnhandledExceptionFilter(unhandledException);
        _set_invalid_parameter_handler(invalidParameter);
        _set_purecall_handler(pureVirtualCall);
        signal(SIGABRT, sigAbortHandler);
        _set_abort_behavior(0, 0);
        EnableCrashingOnCrashes();
        PreventSetUnhandledExceptionFilter();
    }
    

提交回复
热议问题