From 6a844b1d85be2804e1cbf6771f4249f5172b08c7 Mon Sep 17 00:00:00 2001 From: mmentovai Date: Mon, 2 Jul 2007 19:41:05 +0000 Subject: Allow finer control over installed handler types (#193). r=ted.mielczarek http://groups.google.com/group/google-breakpad-dev/browse_thread/thread/992a1bb09dc58a32 git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@193 4c0a9323-5329-0410-9bdc-e9ce6186880e --- src/client/windows/handler/exception_handler.cc | 39 +++++++++++++++---------- src/client/windows/handler/exception_handler.h | 38 +++++++++++++++++------- 2 files changed, 50 insertions(+), 27 deletions(-) (limited to 'src/client') diff --git a/src/client/windows/handler/exception_handler.cc b/src/client/windows/handler/exception_handler.cc index d2c6e7d0..2d7bc57c 100644 --- a/src/client/windows/handler/exception_handler.cc +++ b/src/client/windows/handler/exception_handler.cc @@ -50,7 +50,7 @@ ExceptionHandler::ExceptionHandler(const wstring &dump_path, FilterCallback filter, MinidumpCallback callback, void *callback_context, - bool install_handler) + HandlerType handler_types) : filter_(filter), callback_(callback), callback_context_(callback_context), @@ -62,7 +62,7 @@ ExceptionHandler::ExceptionHandler(const wstring &dump_path, next_minidump_path_c_(NULL), dbghelp_module_(NULL), minidump_write_dump_(NULL), - installed_handler_(install_handler), + handler_types_(handler_types), previous_filter_(NULL), previous_pch_(NULL), handler_thread_(0), @@ -82,11 +82,10 @@ ExceptionHandler::ExceptionHandler(const wstring &dump_path, set_dump_path(dump_path); // Set synchronization primitives and the handler thread. Each - // ExceptionHandler object gets its own handler thread, even if - // install_handler is false, because that's the only way to reliably - // guarantee sufficient stack space in an exception, and the only way to - // get a snapshot of the requesting thread's context outside of an - // exception. + // ExceptionHandler object gets its own handler thread because that's the + // only way to reliably guarantee sufficient stack space in an exception, + // and it allows an easy way to get a snapshot of the requesting thread's + // context outside of an exception. InitializeCriticalSection(&handler_critical_section_); handler_start_semaphore_ = CreateSemaphore(NULL, 0, 1, NULL); handler_finish_semaphore_ = CreateSemaphore(NULL, 0, 1, NULL); @@ -105,7 +104,7 @@ ExceptionHandler::ExceptionHandler(const wstring &dump_path, GetProcAddress(dbghelp_module_, "MiniDumpWriteDump")); } - if (install_handler) { + if (handler_types != HANDLER_NONE) { if (!handler_stack_critical_section_initialized_) { InitializeCriticalSection(&handler_stack_critical_section_); handler_stack_critical_section_initialized_ = true; @@ -119,13 +118,17 @@ ExceptionHandler::ExceptionHandler(const wstring &dump_path, handler_stack_ = new vector(); } handler_stack_->push_back(this); - previous_filter_ = SetUnhandledExceptionFilter(HandleException); + + if (handler_types & HANDLER_EXCEPTION) + previous_filter_ = SetUnhandledExceptionFilter(HandleException); #if _MSC_VER >= 1400 // MSVC 2005/8 - previous_iph_ = _set_invalid_parameter_handler(HandleInvalidParameter); + if (handler_types & HANDLER_INVALID_PARAMETER) + previous_iph_ = _set_invalid_parameter_handler(HandleInvalidParameter); #endif // _MSC_VER >= 1400 - previous_pch_ = _set_purecall_handler(HandlePureVirtualCall); + if (handler_types & HANDLER_PURECALL) + previous_pch_ = _set_purecall_handler(HandlePureVirtualCall); LeaveCriticalSection(&handler_stack_critical_section_); } @@ -136,16 +139,19 @@ ExceptionHandler::~ExceptionHandler() { FreeLibrary(dbghelp_module_); } - if (installed_handler_) { + if (handler_types_ != HANDLER_NONE) { EnterCriticalSection(&handler_stack_critical_section_); - SetUnhandledExceptionFilter(previous_filter_); + if (handler_types_ & HANDLER_EXCEPTION) + SetUnhandledExceptionFilter(previous_filter_); #if _MSC_VER >= 1400 // MSVC 2005/8 - _set_invalid_parameter_handler(previous_iph_); + if (handler_types_ & HANDLER_INVALID_PARAMETER) + _set_invalid_parameter_handler(previous_iph_); #endif // _MSC_VER >= 1400 - _set_purecall_handler(previous_pch_); + if (handler_types_ & HANDLER_PURECALL) + _set_purecall_handler(previous_pch_); if (handler_stack_->back() == this) { handler_stack_->pop_back(); @@ -423,7 +429,8 @@ bool ExceptionHandler::WriteMinidumpForException(EXCEPTION_POINTERS *exinfo) { bool ExceptionHandler::WriteMinidump(const wstring &dump_path, MinidumpCallback callback, void *callback_context) { - ExceptionHandler handler(dump_path, NULL, callback, callback_context, false); + ExceptionHandler handler(dump_path, NULL, callback, callback_context, + HANDLER_NONE); return handler.WriteMinidump(); } diff --git a/src/client/windows/handler/exception_handler.h b/src/client/windows/handler/exception_handler.h index a9eccd6b..c2d55609 100644 --- a/src/client/windows/handler/exception_handler.h +++ b/src/client/windows/handler/exception_handler.h @@ -119,17 +119,33 @@ class ExceptionHandler { MDRawAssertionInfo *assertion, bool succeeded); + // HandlerType specifies which types of handlers should be installed, if + // any. Use HANDLER_NONE for an ExceptionHandler that remains idle, + // without catching any failures on its own. This type of handler may + // still be triggered by calling WriteMinidump. Otherwise, use a + // combination of the other HANDLER_ values, or HANDLER_ALL to install + // all handlers. + enum HandlerType { + HANDLER_NONE = 0, + HANDLER_EXCEPTION = 1 << 0, // SetUnhandledExceptionFilter + HANDLER_INVALID_PARAMETER = 1 << 1, // _set_invalid_parameter_handler + HANDLER_PURECALL = 1 << 2, // _set_purecall_handler + HANDLER_ALL = HANDLER_EXCEPTION | + HANDLER_INVALID_PARAMETER | + HANDLER_PURECALL + }; + // Creates a new ExceptionHandler instance to handle writing minidumps. // Before writing a minidump, the optional filter callback will be called. - // Its return value determines whether or not Breakpad should write a minidump. - // Minidump files will be written to dump_path, and the optional callback - // is called after writing the dump file, as described above. - // If install_handler is true, then a minidump will be written whenever - // an unhandled exception occurs. If it is false, minidumps will only - // be written when WriteMinidump is called. + // Its return value determines whether or not Breakpad should write a + // minidump. Minidump files will be written to dump_path, and the optional + // callback is called after writing the dump file, as described above. + // handler_types specifies the types of handlers that should be installed. ExceptionHandler(const wstring &dump_path, - FilterCallback filter, MinidumpCallback callback, - void *callback_context, bool install_handler); + FilterCallback filter, + MinidumpCallback callback, + void *callback_context, + HandlerType handler_types); ~ExceptionHandler(); // Get and set the minidump path. @@ -244,9 +260,9 @@ class ExceptionHandler { HMODULE dbghelp_module_; MiniDumpWriteDump_type minidump_write_dump_; - // True if the ExceptionHandler installed an unhandled exception filter - // when created (with an install_handler parameter set to true). - bool installed_handler_; + // Tracks the handler types that were installed according to the + // handler_types constructor argument. + HandlerType handler_types_; // When installed_handler_ is true, previous_filter_ is the unhandled // exception filter that was set prior to installing ExceptionHandler as -- cgit v1.2.1