exception_handler.cc.svn-base

来自「SumatraPDF是一款小型开源的pdf阅读工具。虽然玲珑小巧(只有800多K」· SVN-BASE 代码 · 共 534 行 · 第 1/2 页

SVN-BASE
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 + -
显示快捷键?