aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorted.mielczarek <ted.mielczarek@4c0a9323-5329-0410-9bdc-e9ce6186880e>2007-05-10 17:12:14 +0000
committerted.mielczarek <ted.mielczarek@4c0a9323-5329-0410-9bdc-e9ce6186880e>2007-05-10 17:12:14 +0000
commitb86e7ec7f09489a9f6a982a305406dd79a85bbd5 (patch)
tree46a2ce5894c7c8ce74c70d81d809b07dadd81215
parentFixing comment about cpuid vendor_id (diff)
downloadbreakpad-b86e7ec7f09489a9f6a982a305406dd79a85bbd5.tar.xz
Issue 162 - handle pure virtual function calls in VC++. r=mento
git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@166 4c0a9323-5329-0410-9bdc-e9ce6186880e
-rw-r--r--src/client/windows/handler/exception_handler.cc34
-rw-r--r--src/client/windows/handler/exception_handler.h8
-rw-r--r--src/google_breakpad/common/minidump_format.h8
3 files changed, 48 insertions, 2 deletions
diff --git a/src/client/windows/handler/exception_handler.cc b/src/client/windows/handler/exception_handler.cc
index ba14e4d2..5a1444c2 100644
--- a/src/client/windows/handler/exception_handler.cc
+++ b/src/client/windows/handler/exception_handler.cc
@@ -64,6 +64,7 @@ ExceptionHandler::ExceptionHandler(const wstring &dump_path,
minidump_write_dump_(NULL),
installed_handler_(install_handler),
previous_filter_(NULL),
+ previous_pch_(NULL),
handler_thread_(0),
handler_critical_section_(),
handler_start_semaphore_(NULL),
@@ -124,6 +125,8 @@ ExceptionHandler::ExceptionHandler(const wstring &dump_path,
previous_iph_ = _set_invalid_parameter_handler(HandleInvalidParameter);
#endif // _MSC_VER >= 1400
+ previous_pch_ = _set_purecall_handler(HandlePureVirtualCall);
+
LeaveCriticalSection(&handler_stack_critical_section_);
}
}
@@ -142,6 +145,8 @@ ExceptionHandler::~ExceptionHandler() {
_set_invalid_parameter_handler(previous_iph_);
#endif // _MSC_VER >= 1400
+ _set_purecall_handler(previous_pch_);
+
if (handler_stack_->back() == this) {
handler_stack_->pop_back();
} else {
@@ -233,6 +238,7 @@ class AutoExceptionHandler {
#if _MSC_VER >= 1400 // MSVC 2005/8
_set_invalid_parameter_handler(handler_->previous_iph_);
#endif // _MSC_VER >= 1400
+ _set_purecall_handler(handler_->previous_pch_);
}
~AutoExceptionHandler() {
@@ -241,6 +247,7 @@ class AutoExceptionHandler {
#if _MSC_VER >= 1400 // MSVC 2005/8
_set_invalid_parameter_handler(ExceptionHandler::HandleInvalidParameter);
#endif // _MSC_VER >= 1400
+ _set_purecall_handler(ExceptionHandler::HandlePureVirtualCall);
EnterCriticalSection(&ExceptionHandler::handler_stack_critical_section_);
--ExceptionHandler::handler_stack_index_;
@@ -349,6 +356,33 @@ void ExceptionHandler::HandleInvalidParameter(const wchar_t *expression,
}
#endif // _MSC_VER >= 1400
+// static
+void ExceptionHandler::HandlePureVirtualCall() {
+ AutoExceptionHandler auto_exception_handler;
+ ExceptionHandler *current_handler = auto_exception_handler.get_handler();
+
+ MDRawAssertionInfo assertion;
+ memset(&assertion, 0, sizeof(assertion));
+ assertion.type = MD_ASSERTION_INFO_TYPE_PURE_VIRTUAL_CALL;
+
+ if (!current_handler->WriteMinidumpOnHandlerThread(NULL, &assertion)) {
+ if (current_handler->previous_pch_) {
+ // The handler didn't fully handle the exception. Give it to the
+ // previous purecall handler.
+ current_handler->previous_pch_();
+ } else {
+ // If there's no previous handler, return and let _purecall handle it.
+ // This will just put up an assertion dialog.
+ return;
+ }
+ }
+
+ // The handler either took care of the invalid parameter problem itself,
+ // or passed it on to another handler. "Swallow" it by exiting, paralleling
+ // the behavior of "swallowing" exceptions.
+ exit(0);
+}
+
bool ExceptionHandler::WriteMinidumpOnHandlerThread(
EXCEPTION_POINTERS *exinfo, MDRawAssertionInfo *assertion) {
EnterCriticalSection(&handler_critical_section_);
diff --git a/src/client/windows/handler/exception_handler.h b/src/client/windows/handler/exception_handler.h
index f7bfe6cb..e4b3f3bb 100644
--- a/src/client/windows/handler/exception_handler.h
+++ b/src/client/windows/handler/exception_handler.h
@@ -183,6 +183,10 @@ class ExceptionHandler {
uintptr_t reserved);
#endif // _MSC_VER >= 1400
+ // This function will be called by the CRT when a pure virtual
+ // function is called.
+ static void HandlePureVirtualCall();
+
// This is called on the exception thread or on another thread that
// the user wishes to produce a dump from. It calls
// WriteMinidumpWithException on the handler thread, avoiding stack
@@ -254,6 +258,10 @@ class ExceptionHandler {
_invalid_parameter_handler previous_iph_;
#endif // _MSC_VER >= 1400
+ // The CRT allows you to override the default handler for pure
+ // virtual function calls.
+ _purecall_handler previous_pch_;
+
// The exception handler thread.
HANDLE handler_thread_;
diff --git a/src/google_breakpad/common/minidump_format.h b/src/google_breakpad/common/minidump_format.h
index 2f051307..9606dff9 100644
--- a/src/google_breakpad/common/minidump_format.h
+++ b/src/google_breakpad/common/minidump_format.h
@@ -1046,13 +1046,17 @@ typedef struct {
u_int32_t type;
} MDRawAssertionInfo;
-/* For (MDRawAssertionInfo).info: */
+/* For (MDRawAssertionInfo).type: */
typedef enum {
MD_ASSERTION_INFO_TYPE_UNKNOWN = 0,
/* Used for assertions that would be raised by the MSVC CRT but are
* directed to an invalid parameter handler instead. */
- MD_ASSERTION_INFO_TYPE_INVALID_PARAMETER
+ MD_ASSERTION_INFO_TYPE_INVALID_PARAMETER,
+
+ /* Used for assertions that would be raised by the MSVC CRT but are
+ * directed to a pure virtual call handler instead. */
+ MD_ASSERTION_INFO_TYPE_PURE_VIRTUAL_CALL
} MDAssertionInfoData;
#if defined(_MSC_VER)