c++winapi

Difference between EXCEPTION_EXECUTE_HANDLER and EXCEPTION_CONTINUE_SEARCH when used in SetUnhandledExceptionFilter


I have a c++ program on windows that uses SetUnhandledExceptionFilter() at the very start of the program.

The intent is that the unhandledExceptionHandler will store a minidump to disk and then the program will terminate.

In this top-level use-case, I am confused by the possible return values of the exception handler.

EXCEPTION_CONTINUE_SEARCH? There are no other exception handlers to bubble up to (or are there?).

EXCEPTION_EXECUTE_HANDLER?
It's used in the microsoft example but it is unclear what that handler does, since there is no __except block when using SetUnhandledExceptionFilter ...

What are in this case the differences between


Example of the program structure:

LONG WINAPI unhandledExceptionHandler(struct _EXCEPTION_POINTERS* apExceptionInfo)
{
    /* Save a Minidump */
    // ...

    /* Terminate */
    return EXCEPTION_CONTINUE_SEARCH;
}

int main(int argc, char** argv)
{

#ifdef WIN32
    // Enables an application to supersede the top-level exception handler of each thread of a process.
    // After calling this function, if an exception occurs in a process that is not being debugged,
    // and the exception makes it to the unhandled exception filter,
    // that filter will call the exception filter function specified by the lpTopLevelExceptionFilter parameter.
    // Source:
    // https://learn.microsoft.com/en-us/windows/win32/api/errhandlingapi/nf-errhandlingapi-setunhandledexceptionfilter
    SetUnhandledExceptionFilter(unhandledExceptionHandler);

    // related TODO: Do we compile with /EHa ? https://stackoverflow.com/a/4574319/2550406
    // "When you want to make your objects safe for these kind of exceptions as well then you'll need to use /EHa, that tells the compiler to always register the exception filter.
    // Beware of a nasty side-effect of /EHa, it makes catch(...) swallow all exceptions. Including the ones you should never catch, like AV and SO."
#endif

return runTheProgram();
}

Solution

  • Short answer:
    To only store a minidump and do not change normal behavior, just store the minidump and return EXCEPTION_CONTINUE_SEARCH. But pay attention that in some cases your process won't be terminated after executing the filter.

    Long answer:
    The purpose of calling SetUnhandledExceptionFilter is to set a filter, not handler.

    The filter should tell the runtime if in case of specific exception the program should:

    Do not call std::terminate() in the filter function. It would be like:

    Operating system:
    Hey process, we encountered an error, what we should do? Would you like me to sort out the situation for you?

    Process:
    Oh no, I'm in a panic!
    [process terminated]

    Operating system:
    Meh...