exception_handler.cc
来自「SumatraPDF是一款小型开源的pdf阅读工具。虽然玲珑小巧(只有800多K」· CC 代码 · 共 534 行 · 第 1/2 页
CC
534 行
// Copyright (c) 2006, Google Inc.// All rights reserved.//// Redistribution and use in source and binary forms, with or without// modification, are permitted provided that the following conditions are// met://// * Redistributions of source code must retain the above copyright// notice, this list of conditions and the following disclaimer.// * Redistributions in binary form must reproduce the above// copyright notice, this list of conditions and the following disclaimer// in the documentation and/or other materials provided with the// distribution.// * Neither the name of Google Inc. nor the names of its// contributors may be used to endorse or promote products derived from// this software without specific prior written permission.//// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.#include <ObjBase.h>#include <cassert>#include <cstdio>#include "common/windows/string_utils-inl.h"#include "client/windows/handler/exception_handler.h"#include "common/windows/guid_string.h"namespace google_breakpad {static const int kExceptionHandlerThreadInitialStackSize = 64 * 1024;vector<ExceptionHandler *> *ExceptionHandler::handler_stack_ = NULL;LONG ExceptionHandler::handler_stack_index_ = 0;CRITICAL_SECTION ExceptionHandler::handler_stack_critical_section_;bool ExceptionHandler::handler_stack_critical_section_initialized_ = false;ExceptionHandler::ExceptionHandler(const wstring &dump_path, FilterCallback filter, MinidumpCallback callback, void *callback_context, int handler_types) : filter_(filter), callback_(callback), callback_context_(callback_context), dump_path_(), next_minidump_id_(), next_minidump_path_(), dump_path_c_(), next_minidump_id_c_(NULL), next_minidump_path_c_(NULL), dbghelp_module_(NULL), minidump_write_dump_(NULL), handler_types_(handler_types), previous_filter_(NULL), previous_pch_(NULL), handler_thread_(0), handler_critical_section_(), handler_start_semaphore_(NULL), handler_finish_semaphore_(NULL), requesting_thread_id_(0), exception_info_(NULL), assertion_(NULL), handler_return_value_(false) {#if _MSC_VER >= 1400 // MSVC 2005/8 previous_iph_ = NULL;#endif // _MSC_VER >= 1400 // set_dump_path calls UpdateNextID. This sets up all of the path and id // strings, and their equivalent c_str pointers. set_dump_path(dump_path); // Set synchronization primitives and the handler thread. Each // 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); DWORD thread_id; handler_thread_ = CreateThread(NULL, // lpThreadAttributes kExceptionHandlerThreadInitialStackSize, ExceptionHandlerThreadMain, this, // lpParameter 0, // dwCreationFlags &thread_id); dbghelp_module_ = LoadLibraryW(L"dbghelp.dll"); if (dbghelp_module_) { minidump_write_dump_ = reinterpret_cast<MiniDumpWriteDump_type>( GetProcAddress(dbghelp_module_, "MiniDumpWriteDump")); } if (handler_types != HANDLER_NONE) { if (!handler_stack_critical_section_initialized_) { InitializeCriticalSection(&handler_stack_critical_section_); handler_stack_critical_section_initialized_ = true; } EnterCriticalSection(&handler_stack_critical_section_); // The first time an ExceptionHandler that installs a handler is // created, set up the handler stack. if (!handler_stack_) { handler_stack_ = new vector<ExceptionHandler *>(); } handler_stack_->push_back(this); if (handler_types & HANDLER_EXCEPTION) previous_filter_ = SetUnhandledExceptionFilter(HandleException);#if _MSC_VER >= 1400 // MSVC 2005/8 if (handler_types & HANDLER_INVALID_PARAMETER) previous_iph_ = _set_invalid_parameter_handler(HandleInvalidParameter);#endif // _MSC_VER >= 1400 if (handler_types & HANDLER_PURECALL) previous_pch_ = _set_purecall_handler(HandlePureVirtualCall); LeaveCriticalSection(&handler_stack_critical_section_); }}ExceptionHandler::~ExceptionHandler() { if (dbghelp_module_) { FreeLibrary(dbghelp_module_); } if (handler_types_ != HANDLER_NONE) { EnterCriticalSection(&handler_stack_critical_section_); if (handler_types_ & HANDLER_EXCEPTION) SetUnhandledExceptionFilter(previous_filter_);#if _MSC_VER >= 1400 // MSVC 2005/8 if (handler_types_ & HANDLER_INVALID_PARAMETER) _set_invalid_parameter_handler(previous_iph_);#endif // _MSC_VER >= 1400 if (handler_types_ & HANDLER_PURECALL) _set_purecall_handler(previous_pch_); if (handler_stack_->back() == this) { handler_stack_->pop_back(); } else { // TODO(mmentovai): use advapi32!ReportEvent to log the warning to the // system's application event log. fprintf(stderr, "warning: removing Breakpad handler out of order\n"); for (vector<ExceptionHandler *>::iterator iterator = handler_stack_->begin(); iterator != handler_stack_->end(); ++iterator) { if (*iterator == this) { handler_stack_->erase(iterator); } } } if (handler_stack_->empty()) { // When destroying the last ExceptionHandler that installed a handler, // clean up the handler stack. delete handler_stack_; handler_stack_ = NULL; } LeaveCriticalSection(&handler_stack_critical_section_); } // Clean up the handler thread and synchronization primitives. TerminateThread(handler_thread_, 1); DeleteCriticalSection(&handler_critical_section_); CloseHandle(handler_start_semaphore_); CloseHandle(handler_finish_semaphore_);}// staticDWORD ExceptionHandler::ExceptionHandlerThreadMain(void *lpParameter) { ExceptionHandler *self = reinterpret_cast<ExceptionHandler *>(lpParameter); assert(self); while (true) { if (WaitForSingleObject(self->handler_start_semaphore_, INFINITE) == WAIT_OBJECT_0) { // Perform the requested action. self->handler_return_value_ = self->WriteMinidumpWithException( self->requesting_thread_id_, self->exception_info_, self->assertion_); // Allow the requesting thread to proceed. ReleaseSemaphore(self->handler_finish_semaphore_, 1, NULL); } } // Not reached. This thread will be terminated by ExceptionHandler's // destructor. return 0;}// HandleException and HandleInvalidParameter must create an// AutoExceptionHandler object to maintain static state and to determine which// ExceptionHandler instance to use. The constructor locates the correct// instance, and makes it available through get_handler(). The destructor// restores the state in effect prior to allocating the AutoExceptionHandler.class AutoExceptionHandler { public: AutoExceptionHandler() { // Increment handler_stack_index_ so that if another Breakpad handler is // registered using this same HandleException function, and it needs to be // called while this handler is running (either becaause this handler // declines to handle the exception, or an exception occurs during // handling), HandleException will find the appropriate ExceptionHandler // object in handler_stack_ to deliver the exception to. // // Because handler_stack_ is addressed in reverse (as |size - index|), // preincrementing handler_stack_index_ avoids needing to subtract 1 from // the argument to |at|. // // The index is maintained instead of popping elements off of the handler // stack and pushing them at the end of this method. This avoids ruining // the order of elements in the stack in the event that some other thread // decides to manipulate the handler stack (such as creating a new // ExceptionHandler object) while an exception is being handled. EnterCriticalSection(&ExceptionHandler::handler_stack_critical_section_); handler_ = ExceptionHandler::handler_stack_->at( ExceptionHandler::handler_stack_->size() - ++ExceptionHandler::handler_stack_index_); LeaveCriticalSection(&ExceptionHandler::handler_stack_critical_section_); // In case another exception occurs while this handler is doing its thing, // it should be delivered to the previous filter. SetUnhandledExceptionFilter(handler_->previous_filter_);#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() { // Put things back the way they were before entering this handler. SetUnhandledExceptionFilter(ExceptionHandler::HandleException);#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_; LeaveCriticalSection(&ExceptionHandler::handler_stack_critical_section_); } ExceptionHandler *get_handler() const { return handler_; } private: ExceptionHandler *handler_;};
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?