This source file includes following definitions.
- GetInstance
- GetCustomInfo
- OnExceptionCallback
- OnWindowProcedureException
- InitializeCrashReporting
- InitializeCrashReportingForTest
#include "remoting/base/breakpad.h"
#include <windows.h>
#include <string>
#include "base/atomicops.h"
#include "base/file_version_info.h"
#include "base/lazy_instance.h"
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "base/process/memory.h"
#include "base/strings/utf_string_conversions.h"
#include "base/win/wrapped_window_proc.h"
#include "breakpad/src/client/windows/handler/exception_handler.h"
namespace remoting {
void InitializeCrashReportingForTest(const wchar_t* pipe_name);
}
namespace {
const wchar_t kBreakpadProductName[] = L"Chromoting";
const wchar_t kBreakpadVersionEntry[] = L"ver";
const wchar_t kBreakpadVersionDefault[] = L"0.1.0.0";
const wchar_t kBreakpadProdEntry[] = L"prod";
const wchar_t kBreakpadPlatformEntry[] = L"plat";
const wchar_t kBreakpadPlatformWin32[] = L"Win32";
#if defined(_WIN64)
const wchar_t kGoogleUpdatePipeName[] =
L"\\\\.\\pipe\\GoogleCrashServices\\S-1-5-18-x64";
#else
const wchar_t kGoogleUpdatePipeName[] =
L"\\\\.\\pipe\\GoogleCrashServices\\S-1-5-18";
#endif
using base::subtle::AtomicWord;
using base::subtle::NoBarrier_CompareAndSwap;
class BreakpadWin {
public:
BreakpadWin();
~BreakpadWin();
static BreakpadWin* GetInstance();
private:
google_breakpad::CustomClientInfo* GetCustomInfo();
static bool OnExceptionCallback(void* context,
EXCEPTION_POINTERS* exinfo,
MDRawAssertionInfo* assertion);
static int OnWindowProcedureException(EXCEPTION_POINTERS* exinfo);
scoped_ptr<google_breakpad::ExceptionHandler> breakpad_;
volatile AtomicWord handling_exception_;
static const wchar_t* pipe_name_;
friend void ::remoting::InitializeCrashReportingForTest(const wchar_t*);
DISALLOW_COPY_AND_ASSIGN(BreakpadWin);
};
static base::LazyInstance<BreakpadWin>::Leaky g_instance =
LAZY_INSTANCE_INITIALIZER;
const wchar_t* BreakpadWin::pipe_name_ = kGoogleUpdatePipeName;
BreakpadWin::BreakpadWin() : handling_exception_(0) {
_CrtSetReportMode(_CRT_ASSERT, 0);
wchar_t temp_directory[MAX_PATH + 1] = { 0 };
DWORD length = GetTempPath(MAX_PATH, temp_directory);
if (length == 0)
return;
MINIDUMP_TYPE dump_type = static_cast<MINIDUMP_TYPE>(
MiniDumpWithProcessThreadData |
MiniDumpWithUnloadedModules);
breakpad_.reset(
new google_breakpad::ExceptionHandler(
temp_directory, &OnExceptionCallback, NULL, NULL,
google_breakpad::ExceptionHandler::HANDLER_ALL, dump_type,
pipe_name_, GetCustomInfo()));
if (breakpad_->IsOutOfProcess()) {
breakpad_->set_handle_debug_exceptions(true);
}
base::win::WinProcExceptionFilter exception_filter =
base::win::SetWinProcExceptionFilter(&OnWindowProcedureException);
CHECK(!exception_filter);
}
BreakpadWin::~BreakpadWin() {
NOTREACHED();
}
BreakpadWin* BreakpadWin::GetInstance() {
return &g_instance.Get();
}
google_breakpad::CustomClientInfo* BreakpadWin::GetCustomInfo() {
HMODULE binary = base::GetModuleFromAddress(
reinterpret_cast<void*>(&remoting::InitializeCrashReporting));
scoped_ptr<FileVersionInfo> version_info(
FileVersionInfo::CreateFileVersionInfoForModule(binary));
static wchar_t version[64];
if (version_info.get()) {
wcscpy_s(version,
base::UTF16ToWide(version_info->product_version()).c_str());
} else {
wcscpy_s(version, kBreakpadVersionDefault);
}
static google_breakpad::CustomInfoEntry ver_entry(
kBreakpadVersionEntry, version);
static google_breakpad::CustomInfoEntry prod_entry(
kBreakpadProdEntry, kBreakpadProductName);
static google_breakpad::CustomInfoEntry plat_entry(
kBreakpadPlatformEntry, kBreakpadPlatformWin32);
static google_breakpad::CustomInfoEntry entries[] = {
ver_entry, prod_entry, plat_entry };
static google_breakpad::CustomClientInfo custom_info = {
entries, arraysize(entries) };
return &custom_info;
}
bool BreakpadWin::OnExceptionCallback(void* ,
EXCEPTION_POINTERS* ,
MDRawAssertionInfo* ) {
BreakpadWin* self = BreakpadWin::GetInstance();
if (NoBarrier_CompareAndSwap(&self->handling_exception_, 0, 1) != 0) {
::Sleep(INFINITE);
}
return true;
}
int BreakpadWin::OnWindowProcedureException(EXCEPTION_POINTERS* exinfo) {
BreakpadWin* self = BreakpadWin::GetInstance();
if (self->breakpad_.get() != NULL) {
self->breakpad_->WriteMinidumpForException(exinfo);
TerminateProcess(GetCurrentProcess(),
exinfo->ExceptionRecord->ExceptionCode);
}
return EXCEPTION_CONTINUE_SEARCH;
}
}
namespace remoting {
void InitializeCrashReporting() {
BreakpadWin::GetInstance();
}
void InitializeCrashReportingForTest(const wchar_t* pipe_name) {
BreakpadWin::pipe_name_ = pipe_name;
InitializeCrashReporting();
}
}