1

I am trying to print call stack upon exception in Win32/C++ program.

From this article I learned a way to get my handler called upon access violation. But, it seems this only worked in simple console programs.

After I copied the same code into a win32 program with message pump, my handler did not get called.

I think the hook install part is the same, and the only difference is the evil code to trigger access violation is not called soon after the handler installation, but several message pump away from the handler installation.

Does anyone has hint about why my handler was not called?

Let me try to explain my code as below:

void SignalHandler_SegmentViolation(int signal)
{
    StackWalker sw;
    sw.ShowCallstack();
    throw "!Access Violation!";
}
void someFuncionCalledUponButtonClick()
{
    *(int*)0x00 = 5;
}
void myMsgPump()
{
    while(TRUE)
    {
        GetMessage(&msg, NULL, 0, 0);
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
}
int WINAPI WinMain(HINSTANCE hThisInst, HINSTANCE hPrevInst,LPSTR lpszArgs, int nWinMode)
{
    typedef void (*SignalHandlerPointer)(int);

    SignalHandlerPointer previousHandler;
    previousHandler = signal(SIGSEGV , SignalHandler_SegmentViolation);

    try
    {
        myMsgPump();
    }
    catch(char *e)
    {
        printf("Exception Caught: %s\n",e);

        // return control to default handler
        previousHandler(SIGSEGV);
    }
}
Gang Li
  • 37
  • 10
  • 1
    I'd say that what you're doing is *bad!* A signal handler is not called like a normal function in your code, and throwing an exception might now work or even be well-defined (or defined at all). – Some programmer dude Aug 29 '18 at 09:13
  • The code looks like you are trying to gather diagnostics when uncaught exceptions are raised. Instead of using some sort of stack walking code, you might want to have a look into [MiniDumpWriteDump](https://learn.microsoft.com/en-us/windows/desktop/api/minidumpapiset/nf-minidumpapiset-minidumpwritedump). That will generate much more valuable information, and doesn't require you to ship PDB files. Also look into [SetUnhandledExceptionFilter](https://msdn.microsoft.com/en-us/library/windows/desktop/ms680634.aspx), that's what you should be using. – IInspectable Aug 29 '18 at 09:20
  • @IInspectable thanks a lot!! – Gang Li Aug 29 '18 at 09:23

1 Answers1

0

On Windows the signal system and its supporting functions is part of a small compatibility-layer with POSIX (Unix-like systems like Linux or macOS). As such many of the POSIX standard signals aren't really implemented and doesn't work.

One such signal that doesn't work in Windows is the segmentation-fault signal SIGSEGV.

The console-layer (the CRT), which is a layer on top of the WIN32 systems, might have certain signals implemented. And there are other POSIX compatibility systems (e.g. Cygwin) which have their own implementation of signals as well. For direct WIN32 programs there are no such compatibility.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • Do I have a chance to do something, e.g. print call stack, upon access violation? – Gang Li Aug 29 '18 at 09:21
  • @GangLi Windows have something called *structured exceptions*. I don't know if they are able to handle GPF or other crashes. There might also be Windows-specific sub-systems for catching crashes and other problems, but I don't know of them. – Some programmer dude Aug 29 '18 at 09:23
  • 1
    The [SetUnhandledExceptionFilter](https://msdn.microsoft.com/en-us/library/windows/desktop/ms680634.aspx) API allows client code to chain a callback function into the exception handling process. The callback conveniently receives an [EXCEPTION_POINTERS](https://learn.microsoft.com/en-us/windows/desktop/api/winnt/ns-winnt-_exception_pointers) structure, that can be used in a subsequent call to [MiniDumpWriteDump](https://learn.microsoft.com/en-us/windows/desktop/api/minidumpapiset/nf-minidumpapiset-minidumpwritedump) to preserve the callstack at the time the exception was raised. – IInspectable Aug 29 '18 at 10:06
  • @GangLi - of course you can. use only `__try/__except` for this and inside `__except` filter (not handler), also you can use `VEH` – RbMm Aug 29 '18 at 10:23
  • 1
    Although that looks like the perfect solution, on paper, the system may get in your way. Specifically, under certain conditions, the system suppresses uncaught exceptions raised from the [WindowProc](https://msdn.microsoft.com/en-us/library/windows/desktop/ms633573.aspx) callback. Also note, that SEH exception handling and C++ exception handling do not necessarily mix well. – IInspectable Aug 29 '18 at 10:26
  • 1
    The Windows C runtime uses a structured exception handler to implement `SIGSEGV` (i.e. `STATUS_ACCESS_VIOLATION`), `SIGILL` (i.e. `STATUS_ILLEGAL_INSTRUCTION`, `STATUS_PRIVILEGED_INSTRUCTION`), and `SIGFPE` (i.e. `STATUS_FLOAT_DIVIDE_BY_ZERO`, etc). These are 3 of the 6 signals that are required by standard C. They're supported in GUI apps, but the CRT's exception handler might not get called in some contexts. – Eryk Sun Aug 29 '18 at 16:31
  • 1
    VC++ exceptions are implemented using the system exception framework (e.g. `RaiseException`). There are ways to integrate system exceptions (often called "asynchronous", but that's a misnomer) in a C++ try/catch (as opposed to __try/__except), but it's not enouraged. Also, as mentioned, functions called by system components such as the window manager may be guarded by exception handlers that do not chain to application handlers. The system might handle or ignore the exception, or simply terminate the application. – Eryk Sun Aug 29 '18 at 16:36