From b86e7ec7f09489a9f6a982a305406dd79a85bbd5 Mon Sep 17 00:00:00 2001 From: "ted.mielczarek" Date: Thu, 10 May 2007 17:12:14 +0000 Subject: 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 --- src/client/windows/handler/exception_handler.cc | 34 +++++++++++++++++++++++++ src/client/windows/handler/exception_handler.h | 8 ++++++ src/google_breakpad/common/minidump_format.h | 8 ++++-- 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) -- cgit v1.2.1