Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Convert std::exception to EXCEPTION_POINTERS

I may be completely misunderstanding how to use the Google Breakpad API, and am open to comments / suggestions / rude remarks if that is the case. I am trying to call the following C++ function:

bool WriteMinidumpForException(EXCEPTION_POINTERS* exinfo);

I have a reference to a std::exception:

try {
  return QApplication::notify(receiver, event);
} catch (std::exception &ex) {
  eh_.WriteMinidumpForException(?????);
  // ... do some more stuff and ultimately kill this process
}

(eh_ is a google_breakpad::ExceptionHandler.)

What do I put in the ?????

Background: The reason this is necessary (I think) is that Qt will not support an exception thrown in an event handler. It will not propagate correctly, and thus the minidump that Breakpad produces is completely useless because the actual context of the exception has been lost. Instead, you must catch all exceptions and handle them in the override of QApplication::notify(), which is what I am trying to do. In the case of an exception, I want to immediately write my minidump for that exception (which is sounds like WriteMinidumpForException will do) and then notify the user and quit the application. But I am not sure what to pass as the EXCEPTION_POINTERS* parameter.

like image 464
Dave Mateer Avatar asked Mar 15 '11 17:03

Dave Mateer


2 Answers

In the MSVC compiler, C++ exceptions piggy-back onto the native Windows exception plumbing (SEH, Structured Exception Handling). There's a pretty big impedance mismatch though, the concept of an exception filter is doesn't have a good match in C++. By the time the catch handler catches an exception, the SEH exception is already handled and the stack unwound. The EXCEPTION_POINTERS info is gonzo. The exception filters actually exist, that's how it filters for the specific type you want to catch, they are however auto-generated by the compiler. No reasonable C++ syntax exists to make them useful.

You need to dip into the compiler support for handling SEH exceptions. Use the __try, __except keywords (__finally is optional) and have your filter catch the exception code for a C++ exception, 0xe04d5343 ('MSC'). You do however lose the ability to catch a specific C++ exception type, that plumbing is buried in the CRT without source. Put a C++ try inside the __try to fix that so your __except only sees exceptions that the C++ code didn't filter.

Using SetUnhandledExceptionFilter() is another way to do this btw, you really should consider it to act as the ultimate backstop of any unhandled exception, independent of the code location. It is the best way to create a minidump of a crashing app. Last but not least, creating a minidump of a crashing app inside the process itself isn't the best approach. There are plenty of odds that this won't work well, the process state can be corrupted pretty badly. One failure mode is having the process heap locked. Not unlikely considering that heap damage is a very common crash reason. Fix that with a "guard process", use a named event to signal it to make a minidump. Your exception filter only needs to set the event, that always works.

like image 70
Hans Passant Avatar answered Oct 24 '22 05:10

Hans Passant


Windows SEH and c++ exceptions are not intertwined in any way - the easy way to solve this is to use your own __try __except wrapping e.g. a dereference of a null pointer.

Something like:

__try {
  * (int *) 0 = 0;
} 
__except 
    (
        eh_.WriteMinidumpForException(GetExceptionInformation()), EXCEPTION_EXECUTE_HANDLER
    ) 
{
}
like image 43
Erik Avatar answered Oct 24 '22 07:10

Erik