diff options
author | wolfbeast <mcwerewolf@wolfbeast.com> | 2019-04-01 13:05:24 +0200 |
---|---|---|
committer | wolfbeast <mcwerewolf@wolfbeast.com> | 2019-04-01 13:05:24 +0200 |
commit | ff2f287f82630ab3887d7d5c1e64e5b888ea0beb (patch) | |
tree | 4e96cb32aa2320a327024942d247c6b56ef8c199 /toolkit/crashreporter/google-breakpad/src/client/windows/crash_generation | |
parent | bfc97728065cbbc7f6bbc281b654a2d1e079b48d (diff) | |
download | UXP-ff2f287f82630ab3887d7d5c1e64e5b888ea0beb.tar UXP-ff2f287f82630ab3887d7d5c1e64e5b888ea0beb.tar.gz UXP-ff2f287f82630ab3887d7d5c1e64e5b888ea0beb.tar.lz UXP-ff2f287f82630ab3887d7d5c1e64e5b888ea0beb.tar.xz UXP-ff2f287f82630ab3887d7d5c1e64e5b888ea0beb.zip |
Remove crashreporter toolkit files.
Resolves #20
Diffstat (limited to 'toolkit/crashreporter/google-breakpad/src/client/windows/crash_generation')
11 files changed, 0 insertions, 3133 deletions
diff --git a/toolkit/crashreporter/google-breakpad/src/client/windows/crash_generation/ReadMe.txt b/toolkit/crashreporter/google-breakpad/src/client/windows/crash_generation/ReadMe.txt deleted file mode 100644 index b54d0e11b..000000000 --- a/toolkit/crashreporter/google-breakpad/src/client/windows/crash_generation/ReadMe.txt +++ /dev/null @@ -1,58 +0,0 @@ -========================================================================= - State machine transitions for the Crash Generation Server -========================================================================= - -========================================================================= - | - STATE | ACTIONS - | -========================================================================= - ERROR | Clean up resources used to serve clients. - | Always remain in ERROR state. -------------------------------------------------------------------------- - INITIAL | Connect to the pipe asynchronously. - | If connection is successfully queued up asynchronously, - | go into CONNECTING state. - | If connection is done synchronously, go into CONNECTED - | state. - | For any unexpected problems, go into ERROR state. -------------------------------------------------------------------------- - CONNECTING | Get the result of async connection request. - | If I/O is still incomplete, remain in the CONNECTING - | state. - | If connection is complete, go into CONNECTED state. - | For any unexpected problems, go into DISCONNECTING state. -------------------------------------------------------------------------- - CONNECTED | Read from the pipe asynchronously. - | If read request is successfully queued up asynchronously, - | go into READING state. - | For any unexpected problems, go into DISCONNECTING state. -------------------------------------------------------------------------- - READING | Get the result of async read request. - | If read is done, go into READ_DONE state. - | For any unexpected problems, go into DISCONNECTING state. -------------------------------------------------------------------------- - READ_DONE | Register the client, prepare the reply and write the - | reply to the pipe asynchronously. - | If write request is successfully queued up asynchronously, - | go into WRITING state. - | For any unexpected problems, go into DISCONNECTING state. -------------------------------------------------------------------------- - WRITING | Get the result of the async write request. - | If write is done, go into WRITE_DONE state. - | For any unexpected problems, go into DISCONNECTING state. -------------------------------------------------------------------------- - WRITE_DONE | Read from the pipe asynchronously (for an ACK). - | If read request is successfully queued up asynchonously, - | go into READING_ACK state. - | For any unexpected problems, go into DISCONNECTING state. -------------------------------------------------------------------------- - READING_ACK | Get the result of the async read request. - | If read is done, perform action for successful client - | connection. - | Go into DISCONNECTING state. -------------------------------------------------------------------------- - DISCONNECTING | Disconnect from the pipe, reset the event and go into - | INITIAL state and signal the event again. If anything - | fails, go into ERROR state. -========================================================================= diff --git a/toolkit/crashreporter/google-breakpad/src/client/windows/crash_generation/client_info.cc b/toolkit/crashreporter/google-breakpad/src/client/windows/crash_generation/client_info.cc deleted file mode 100644 index ed3126381..000000000 --- a/toolkit/crashreporter/google-breakpad/src/client/windows/crash_generation/client_info.cc +++ /dev/null @@ -1,223 +0,0 @@ -// Copyright (c) 2008, 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 "client/windows/crash_generation/client_info.h" -#include "client/windows/common/ipc_protocol.h" - -static const wchar_t kCustomInfoProcessUptimeName[] = L"ptime"; -static const size_t kMaxCustomInfoEntries = 4096; - -namespace google_breakpad { - -ClientInfo::ClientInfo(CrashGenerationServer* crash_server, - DWORD pid, - MINIDUMP_TYPE dump_type, - DWORD* thread_id, - EXCEPTION_POINTERS** ex_info, - MDRawAssertionInfo* assert_info, - const CustomClientInfo& custom_client_info) - : crash_server_(crash_server), - pid_(pid), - dump_type_(dump_type), - ex_info_(ex_info), - assert_info_(assert_info), - custom_client_info_(custom_client_info), - thread_id_(thread_id), - process_handle_(NULL), - dump_requested_handle_(NULL), - dump_generated_handle_(NULL), - dump_request_wait_handle_(NULL), - process_exit_wait_handle_(NULL), - crash_id_(NULL) { - GetSystemTimeAsFileTime(&start_time_); -} - -bool ClientInfo::Initialize() { - process_handle_ = OpenProcess(GENERIC_ALL, FALSE, pid_); - if (!process_handle_) { - return false; - } - - // The crash_id will be the low order word of the process creation time. - FILETIME creation_time, exit_time, kernel_time, user_time; - if (GetProcessTimes(process_handle_, &creation_time, &exit_time, - &kernel_time, &user_time)) { - start_time_ = creation_time; - } - crash_id_ = start_time_.dwLowDateTime; - - dump_requested_handle_ = CreateEvent(NULL, // Security attributes. - TRUE, // Manual reset. - FALSE, // Initial state. - NULL); // Name. - if (!dump_requested_handle_) { - return false; - } - - dump_generated_handle_ = CreateEvent(NULL, // Security attributes. - TRUE, // Manual reset. - FALSE, // Initial state. - NULL); // Name. - return dump_generated_handle_ != NULL; -} - -void ClientInfo::UnregisterDumpRequestWaitAndBlockUntilNoPending() { - if (dump_request_wait_handle_) { - // Wait for callbacks that might already be running to finish. - UnregisterWaitEx(dump_request_wait_handle_, INVALID_HANDLE_VALUE); - dump_request_wait_handle_ = NULL; - } -} - -void ClientInfo::UnregisterProcessExitWait(bool block_until_no_pending) { - if (process_exit_wait_handle_) { - if (block_until_no_pending) { - // Wait for the callback that might already be running to finish. - UnregisterWaitEx(process_exit_wait_handle_, INVALID_HANDLE_VALUE); - } else { - UnregisterWait(process_exit_wait_handle_); - } - process_exit_wait_handle_ = NULL; - } -} - -ClientInfo::~ClientInfo() { - // Waiting for the callback to finish here is safe because ClientInfo's are - // never destroyed from the dump request handling callback. - UnregisterDumpRequestWaitAndBlockUntilNoPending(); - - // This is a little tricky because ClientInfo's may be destroyed by the same - // callback (OnClientEnd) and waiting for it to finish will cause a deadlock. - // Regardless of this complication, wait for any running callbacks to finish - // so that the common case is properly handled. In order to avoid deadlocks, - // the OnClientEnd callback must call UnregisterProcessExitWait(false) - // before deleting the ClientInfo. - UnregisterProcessExitWait(true); - - if (process_handle_) { - CloseHandle(process_handle_); - } - - if (dump_requested_handle_) { - CloseHandle(dump_requested_handle_); - } - - if (dump_generated_handle_) { - CloseHandle(dump_generated_handle_); - } -} - -bool ClientInfo::GetClientExceptionInfo(EXCEPTION_POINTERS** ex_info) const { - SIZE_T bytes_count = 0; - if (!ReadProcessMemory(process_handle_, - ex_info_, - ex_info, - sizeof(*ex_info), - &bytes_count)) { - return false; - } - - return bytes_count == sizeof(*ex_info); -} - -bool ClientInfo::GetClientThreadId(DWORD* thread_id) const { - SIZE_T bytes_count = 0; - if (!ReadProcessMemory(process_handle_, - thread_id_, - thread_id, - sizeof(*thread_id), - &bytes_count)) { - return false; - } - - return bytes_count == sizeof(*thread_id); -} - -void ClientInfo::SetProcessUptime() { - FILETIME now = {0}; - GetSystemTimeAsFileTime(&now); - - ULARGE_INTEGER time_start; - time_start.HighPart = start_time_.dwHighDateTime; - time_start.LowPart = start_time_.dwLowDateTime; - - ULARGE_INTEGER time_now; - time_now.HighPart = now.dwHighDateTime; - time_now.LowPart = now.dwLowDateTime; - - // Calculate the delay and convert it from 100-nanoseconds to milliseconds. - __int64 delay = (time_now.QuadPart - time_start.QuadPart) / 10 / 1000; - - // Convert it to a string. - wchar_t* value = custom_info_entries_.get()[custom_client_info_.count].value; - _i64tow_s(delay, value, CustomInfoEntry::kValueMaxLength, 10); -} - -bool ClientInfo::PopulateCustomInfo() { - if (custom_client_info_.count > kMaxCustomInfoEntries) - return false; - - SIZE_T bytes_count = 0; - SIZE_T read_count = sizeof(CustomInfoEntry) * custom_client_info_.count; - - // If the scoped array for custom info already has an array, it will be - // the same size as what we need. This is because the number of custom info - // entries is always the same. So allocate memory only if scoped array has - // a NULL pointer. - if (!custom_info_entries_.get()) { - // Allocate an extra entry for reporting uptime for the client process. - custom_info_entries_.reset( - new CustomInfoEntry[custom_client_info_.count + 1]); - // Use the last element in the array for uptime. - custom_info_entries_.get()[custom_client_info_.count].set_name( - kCustomInfoProcessUptimeName); - } - - if (!ReadProcessMemory(process_handle_, - custom_client_info_.entries, - custom_info_entries_.get(), - read_count, - &bytes_count)) { - return false; - } - - SetProcessUptime(); - return (bytes_count == read_count); -} - -CustomClientInfo ClientInfo::GetCustomInfo() const { - CustomClientInfo custom_info; - custom_info.entries = custom_info_entries_.get(); - // Add 1 to the count from the client process to account for extra entry for - // process uptime. - custom_info.count = custom_client_info_.count + 1; - return custom_info; -} - -} // namespace google_breakpad diff --git a/toolkit/crashreporter/google-breakpad/src/client/windows/crash_generation/client_info.h b/toolkit/crashreporter/google-breakpad/src/client/windows/crash_generation/client_info.h deleted file mode 100644 index 6a8fba31f..000000000 --- a/toolkit/crashreporter/google-breakpad/src/client/windows/crash_generation/client_info.h +++ /dev/null @@ -1,177 +0,0 @@ -// Copyright (c) 2008, 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. - -#ifndef CLIENT_WINDOWS_CRASH_GENERATION_CLIENT_INFO_H__ -#define CLIENT_WINDOWS_CRASH_GENERATION_CLIENT_INFO_H__ - -#include <windows.h> -#include <dbghelp.h> -#include "client/windows/common/ipc_protocol.h" -#include "common/scoped_ptr.h" -#include "google_breakpad/common/minidump_format.h" - -namespace google_breakpad { - -class CrashGenerationServer; - -// Abstraction for a crash client process. -class ClientInfo { - public: - // Creates an instance with the given values. Gets the process - // handle for the given process id and creates necessary event - // objects. - ClientInfo(CrashGenerationServer* crash_server, - DWORD pid, - MINIDUMP_TYPE dump_type, - DWORD* thread_id, - EXCEPTION_POINTERS** ex_info, - MDRawAssertionInfo* assert_info, - const CustomClientInfo& custom_client_info); - - ~ClientInfo(); - - CrashGenerationServer* crash_server() const { return crash_server_; } - DWORD pid() const { return pid_; } - MINIDUMP_TYPE dump_type() const { return dump_type_; } - EXCEPTION_POINTERS** ex_info() const { return ex_info_; } - MDRawAssertionInfo* assert_info() const { return assert_info_; } - DWORD* thread_id() const { return thread_id_; } - HANDLE process_handle() const { return process_handle_; } - HANDLE dump_requested_handle() const { return dump_requested_handle_; } - HANDLE dump_generated_handle() const { return dump_generated_handle_; } - DWORD crash_id() const { return crash_id_; } - const CustomClientInfo& custom_client_info() const { - return custom_client_info_; - } - - void set_dump_request_wait_handle(HANDLE value) { - dump_request_wait_handle_ = value; - } - - void set_process_exit_wait_handle(HANDLE value) { - process_exit_wait_handle_ = value; - } - - // Unregister the dump request wait operation and wait for all callbacks - // that might already be running to complete before returning. - void UnregisterDumpRequestWaitAndBlockUntilNoPending(); - - // Unregister the process exit wait operation. If block_until_no_pending is - // true, wait for all callbacks that might already be running to complete - // before returning. - void UnregisterProcessExitWait(bool block_until_no_pending); - - bool Initialize(); - bool GetClientExceptionInfo(EXCEPTION_POINTERS** ex_info) const; - bool GetClientThreadId(DWORD* thread_id) const; - - // Reads the custom information from the client process address space. - bool PopulateCustomInfo(); - - // Returns the client custom information. - CustomClientInfo GetCustomInfo() const; - - private: - // Calcualtes the uptime for the client process, converts it to a string and - // stores it in the last entry of client custom info. - void SetProcessUptime(); - - // Crash generation server. - CrashGenerationServer* crash_server_; - - // Client process ID. - DWORD pid_; - - // Dump type requested by the client. - MINIDUMP_TYPE dump_type_; - - // Address of an EXCEPTION_POINTERS* variable in the client - // process address space that will point to an instance of - // EXCEPTION_POINTERS containing information about crash. - // - // WARNING: Do not dereference these pointers as they are pointers - // in the address space of another process. - EXCEPTION_POINTERS** ex_info_; - - // Address of an instance of MDRawAssertionInfo in the client - // process address space that will contain information about - // non-exception related crashes like invalid parameter assertion - // failures and pure calls. - // - // WARNING: Do not dereference these pointers as they are pointers - // in the address space of another process. - MDRawAssertionInfo* assert_info_; - - // Custom information about the client. - CustomClientInfo custom_client_info_; - - // Contains the custom client info entries read from the client process - // memory. This will be populated only if the method GetClientCustomInfo - // is called. - scoped_array<CustomInfoEntry> custom_info_entries_; - - // Address of a variable in the client process address space that - // will contain the thread id of the crashing client thread. - // - // WARNING: Do not dereference these pointers as they are pointers - // in the address space of another process. - DWORD* thread_id_; - - // Client process handle. - HANDLE process_handle_; - - // Dump request event handle. - HANDLE dump_requested_handle_; - - // Dump generated event handle. - HANDLE dump_generated_handle_; - - // Wait handle for dump request event. - HANDLE dump_request_wait_handle_; - - // Wait handle for process exit event. - HANDLE process_exit_wait_handle_; - - // Time when the client process started. It is used to determine the uptime - // for the client process when it signals a crash. - FILETIME start_time_; - - // The crash id which can be used to request an upload. This will be the - // value of the low order dword of the process creation time for the process - // being dumped. - DWORD crash_id_; - - // Disallow copy ctor and operator=. - ClientInfo(const ClientInfo& client_info); - ClientInfo& operator=(const ClientInfo& client_info); -}; - -} // namespace google_breakpad - -#endif // CLIENT_WINDOWS_CRASH_GENERATION_CLIENT_INFO_H__ diff --git a/toolkit/crashreporter/google-breakpad/src/client/windows/crash_generation/crash_generation.gyp b/toolkit/crashreporter/google-breakpad/src/client/windows/crash_generation/crash_generation.gyp deleted file mode 100644 index ba343768a..000000000 --- a/toolkit/crashreporter/google-breakpad/src/client/windows/crash_generation/crash_generation.gyp +++ /dev/null @@ -1,63 +0,0 @@ -# Copyright 2010 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. - -{ - 'includes': [ - '../../../build/common.gypi', - ], - 'targets': [ - { - 'target_name': 'crash_generation_server', - 'type': 'static_library', - 'sources': [ - 'client_info.cc', - 'crash_generation_server.cc', - 'minidump_generator.cc', - 'client_info.h', - 'crash_generation_client.h', - 'crash_generation_server.h', - 'minidump_generator.h', - ], - 'dependencies': [ - '../breakpad_client.gyp:common' - ], - }, - { - 'target_name': 'crash_generation_client', - 'type': 'static_library', - 'include_dirs': [ - '<(DEPTH)', - ], - 'sources': [ - 'crash_generation_client.h', - 'crash_generation_client.cc', - 'crash_generation_server.h', - ], - }, - ], -} diff --git a/toolkit/crashreporter/google-breakpad/src/client/windows/crash_generation/crash_generation_client.cc b/toolkit/crashreporter/google-breakpad/src/client/windows/crash_generation/crash_generation_client.cc deleted file mode 100644 index 3ba5d4e4f..000000000 --- a/toolkit/crashreporter/google-breakpad/src/client/windows/crash_generation/crash_generation_client.cc +++ /dev/null @@ -1,405 +0,0 @@ -// Copyright (c) 2008, 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 "client/windows/crash_generation/crash_generation_client.h" -#include <cassert> -#include <utility> -#include "client/windows/common/ipc_protocol.h" - -namespace google_breakpad { - -const int kPipeBusyWaitTimeoutMs = 2000; - -#ifdef _DEBUG -const DWORD kWaitForServerTimeoutMs = INFINITE; -#else -const DWORD kWaitForServerTimeoutMs = 15000; -#endif - -const int kPipeConnectMaxAttempts = 2; - -const DWORD kPipeDesiredAccess = FILE_READ_DATA | - FILE_WRITE_DATA | - FILE_WRITE_ATTRIBUTES; - -const DWORD kPipeFlagsAndAttributes = SECURITY_IDENTIFICATION | - SECURITY_SQOS_PRESENT; - -const DWORD kPipeMode = PIPE_READMODE_MESSAGE; - -const size_t kWaitEventCount = 2; - -// This function is orphan for production code. It can be used -// for debugging to help repro some scenarios like the client -// is slow in writing to the pipe after connecting, the client -// is slow in reading from the pipe after writing, etc. The parameter -// overlapped below is not used and it is present to match the signature -// of this function to TransactNamedPipe Win32 API. Uncomment if needed -// for debugging. -/** -static bool TransactNamedPipeDebugHelper(HANDLE pipe, - const void* in_buffer, - DWORD in_size, - void* out_buffer, - DWORD out_size, - DWORD* bytes_count, - LPOVERLAPPED) { - // Uncomment the next sleep to create a gap before writing - // to pipe. - // Sleep(5000); - - if (!WriteFile(pipe, - in_buffer, - in_size, - bytes_count, - NULL)) { - return false; - } - - // Uncomment the next sleep to create a gap between write - // and read. - // Sleep(5000); - - return ReadFile(pipe, out_buffer, out_size, bytes_count, NULL) != FALSE; -} -**/ - -CrashGenerationClient::CrashGenerationClient( - const wchar_t* pipe_name, - MINIDUMP_TYPE dump_type, - const CustomClientInfo* custom_info) - : pipe_name_(pipe_name), - pipe_handle_(NULL), - custom_info_(), - dump_type_(dump_type), - crash_event_(NULL), - crash_generated_(NULL), - server_alive_(NULL), - server_process_id_(0), - thread_id_(0), - exception_pointers_(NULL) { - memset(&assert_info_, 0, sizeof(assert_info_)); - if (custom_info) { - custom_info_ = *custom_info; - } -} - -CrashGenerationClient::CrashGenerationClient( - HANDLE pipe_handle, - MINIDUMP_TYPE dump_type, - const CustomClientInfo* custom_info) - : pipe_name_(), - pipe_handle_(pipe_handle), - custom_info_(), - dump_type_(dump_type), - crash_event_(NULL), - crash_generated_(NULL), - server_alive_(NULL), - server_process_id_(0), - thread_id_(0), - exception_pointers_(NULL) { - memset(&assert_info_, 0, sizeof(assert_info_)); - if (custom_info) { - custom_info_ = *custom_info; - } -} - -CrashGenerationClient::~CrashGenerationClient() { - if (crash_event_) { - CloseHandle(crash_event_); - } - - if (crash_generated_) { - CloseHandle(crash_generated_); - } - - if (server_alive_) { - CloseHandle(server_alive_); - } -} - -// Performs the registration step with the server process. -// The registration step involves communicating with the server -// via a named pipe. The client sends the following pieces of -// data to the server: -// -// * Message tag indicating the client is requesting registration. -// * Process id of the client process. -// * Address of a DWORD variable in the client address space -// that will contain the thread id of the client thread that -// caused the crash. -// * Address of a EXCEPTION_POINTERS* variable in the client -// address space that will point to an instance of EXCEPTION_POINTERS -// when the crash happens. -// * Address of an instance of MDRawAssertionInfo that will contain -// relevant information in case of non-exception crashes like assertion -// failures and pure calls. -// -// In return the client expects the following information from the server: -// -// * Message tag indicating successful registration. -// * Server process id. -// * Handle to an object that client can signal to request dump -// generation from the server. -// * Handle to an object that client can wait on after requesting -// dump generation for the server to finish dump generation. -// * Handle to a mutex object that client can wait on to make sure -// server is still alive. -// -// If any step of the expected behavior mentioned above fails, the -// registration step is not considered successful and hence out-of-process -// dump generation service is not available. -// -// Returns true if the registration is successful; false otherwise. -bool CrashGenerationClient::Register() { - if (IsRegistered()) { - return true; - } - - HANDLE pipe = ConnectToServer(); - if (!pipe) { - return false; - } - - bool success = RegisterClient(pipe); - CloseHandle(pipe); - return success; -} - -bool CrashGenerationClient::RequestUpload(DWORD crash_id) { - HANDLE pipe = ConnectToServer(); - if (!pipe) { - return false; - } - - CustomClientInfo custom_info = {NULL, 0}; - ProtocolMessage msg(MESSAGE_TAG_UPLOAD_REQUEST, crash_id, - static_cast<MINIDUMP_TYPE>(NULL), NULL, NULL, NULL, - custom_info, NULL, NULL, NULL); - DWORD bytes_count = 0; - bool success = WriteFile(pipe, &msg, sizeof(msg), &bytes_count, NULL) != 0; - - CloseHandle(pipe); - return success; -} - -HANDLE CrashGenerationClient::ConnectToServer() { - HANDLE pipe = ConnectToPipe(pipe_name_.c_str(), - kPipeDesiredAccess, - kPipeFlagsAndAttributes); - if (!pipe) { - return NULL; - } - - DWORD mode = kPipeMode; - if (!SetNamedPipeHandleState(pipe, &mode, NULL, NULL)) { - CloseHandle(pipe); - pipe = NULL; - } - - return pipe; -} - -bool CrashGenerationClient::RegisterClient(HANDLE pipe) { - ProtocolMessage msg(MESSAGE_TAG_REGISTRATION_REQUEST, - GetCurrentProcessId(), - dump_type_, - &thread_id_, - &exception_pointers_, - &assert_info_, - custom_info_, - NULL, - NULL, - NULL); - ProtocolMessage reply; - DWORD bytes_count = 0; - // The call to TransactNamedPipe below can be changed to a call - // to TransactNamedPipeDebugHelper to help repro some scenarios. - // For details see comments for TransactNamedPipeDebugHelper. - if (!TransactNamedPipe(pipe, - &msg, - sizeof(msg), - &reply, - sizeof(ProtocolMessage), - &bytes_count, - NULL)) { - return false; - } - - if (!ValidateResponse(reply)) { - return false; - } - - ProtocolMessage ack_msg; - ack_msg.tag = MESSAGE_TAG_REGISTRATION_ACK; - - if (!WriteFile(pipe, &ack_msg, sizeof(ack_msg), &bytes_count, NULL)) { - return false; - } - crash_event_ = reply.dump_request_handle; - crash_generated_ = reply.dump_generated_handle; - server_alive_ = reply.server_alive_handle; - server_process_id_ = reply.id; - - return true; -} - -HANDLE CrashGenerationClient::ConnectToPipe(const wchar_t* pipe_name, - DWORD pipe_access, - DWORD flags_attrs) { - if (pipe_handle_) { - HANDLE t = pipe_handle_; - pipe_handle_ = NULL; - return t; - } - - for (int i = 0; i < kPipeConnectMaxAttempts; ++i) { - HANDLE pipe = CreateFile(pipe_name, - pipe_access, - 0, - NULL, - OPEN_EXISTING, - flags_attrs, - NULL); - if (pipe != INVALID_HANDLE_VALUE) { - return pipe; - } - - // Cannot continue retrying if error is something other than - // ERROR_PIPE_BUSY. - if (GetLastError() != ERROR_PIPE_BUSY) { - break; - } - - // Cannot continue retrying if wait on pipe fails. - if (!WaitNamedPipe(pipe_name, kPipeBusyWaitTimeoutMs)) { - break; - } - } - - return NULL; -} - -bool CrashGenerationClient::ValidateResponse( - const ProtocolMessage& msg) const { - return (msg.tag == MESSAGE_TAG_REGISTRATION_RESPONSE) && - (msg.id != 0) && - (msg.dump_request_handle != NULL) && - (msg.dump_generated_handle != NULL) && - (msg.server_alive_handle != NULL); -} - -bool CrashGenerationClient::IsRegistered() const { - return crash_event_ != NULL; -} - -bool CrashGenerationClient::RequestDump(EXCEPTION_POINTERS* ex_info, - MDRawAssertionInfo* assert_info) { - if (!IsRegistered()) { - return false; - } - - exception_pointers_ = ex_info; - thread_id_ = GetCurrentThreadId(); - - if (assert_info) { - memcpy(&assert_info_, assert_info, sizeof(assert_info_)); - } else { - memset(&assert_info_, 0, sizeof(assert_info_)); - } - - return SignalCrashEventAndWait(); -} - -bool CrashGenerationClient::RequestDump(EXCEPTION_POINTERS* ex_info) { - return RequestDump(ex_info, NULL); -} - -bool CrashGenerationClient::RequestDump(MDRawAssertionInfo* assert_info) { - return RequestDump(NULL, assert_info); -} - -bool CrashGenerationClient::SignalCrashEventAndWait() { - assert(crash_event_); - assert(crash_generated_); - assert(server_alive_); - - // Reset the dump generated event before signaling the crash - // event so that the server can set the dump generated event - // once it is done generating the event. - if (!ResetEvent(crash_generated_)) { - return false; - } - - if (!SetEvent(crash_event_)) { - return false; - } - - HANDLE wait_handles[kWaitEventCount] = {crash_generated_, server_alive_}; - - DWORD result = WaitForMultipleObjects(kWaitEventCount, - wait_handles, - FALSE, - kWaitForServerTimeoutMs); - - // Crash dump was successfully generated only if the server - // signaled the crash generated event. - return result == WAIT_OBJECT_0; -} - -HANDLE CrashGenerationClient::DuplicatePipeToClientProcess(const wchar_t* pipe_name, - HANDLE hProcess) { - for (int i = 0; i < kPipeConnectMaxAttempts; ++i) { - HANDLE local_pipe = CreateFile(pipe_name, kPipeDesiredAccess, - 0, NULL, OPEN_EXISTING, - kPipeFlagsAndAttributes, NULL); - if (local_pipe != INVALID_HANDLE_VALUE) { - HANDLE remotePipe = INVALID_HANDLE_VALUE; - if (DuplicateHandle(GetCurrentProcess(), local_pipe, - hProcess, &remotePipe, 0, FALSE, - DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS)) { - return remotePipe; - } else { - return INVALID_HANDLE_VALUE; - } - } - - // Cannot continue retrying if the error wasn't a busy pipe. - if (GetLastError() != ERROR_PIPE_BUSY) { - return INVALID_HANDLE_VALUE; - } - - if (!WaitNamedPipe(pipe_name, kPipeBusyWaitTimeoutMs)) { - return INVALID_HANDLE_VALUE; - } - } - return INVALID_HANDLE_VALUE; -} - -} // namespace google_breakpad diff --git a/toolkit/crashreporter/google-breakpad/src/client/windows/crash_generation/crash_generation_client.h b/toolkit/crashreporter/google-breakpad/src/client/windows/crash_generation/crash_generation_client.h deleted file mode 100644 index 457f73195..000000000 --- a/toolkit/crashreporter/google-breakpad/src/client/windows/crash_generation/crash_generation_client.h +++ /dev/null @@ -1,182 +0,0 @@ -// Copyright (c) 2008, 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. - -#ifndef CLIENT_WINDOWS_CRASH_GENERATION_CRASH_GENERATION_CLIENT_H_ -#define CLIENT_WINDOWS_CRASH_GENERATION_CRASH_GENERATION_CLIENT_H_ - -#include <windows.h> -#include <dbghelp.h> -#include <string> -#include <utility> -#include "client/windows/common/ipc_protocol.h" -#include "common/scoped_ptr.h" - -namespace google_breakpad { - -struct CustomClientInfo; - -// Abstraction of client-side implementation of out of process -// crash generation. -// -// The process that desires to have out-of-process crash dump -// generation service can use this class in the following way: -// -// * Create an instance. -// * Call Register method so that the client tries to register -// with the server process and check the return value. If -// registration is not successful, out-of-process crash dump -// generation will not be available -// * Request dump generation by calling either of the two -// overloaded RequestDump methods - one in case of exceptions -// and the other in case of assertion failures -// -// Note that it is the responsibility of the client code of -// this class to set the unhandled exception filter with the -// system by calling the SetUnhandledExceptionFilter function -// and the client code should explicitly request dump generation. -class CrashGenerationClient { - public: - CrashGenerationClient(const wchar_t* pipe_name, - MINIDUMP_TYPE dump_type, - const CustomClientInfo* custom_info); - - CrashGenerationClient(HANDLE pipe_handle, - MINIDUMP_TYPE dump_type, - const CustomClientInfo* custom_info); - - ~CrashGenerationClient(); - - // Registers the client process with the crash server. - // - // Returns true if the registration is successful; false otherwise. - bool Register(); - - // Requests the crash server to upload a previous dump with the - // given crash id. - bool RequestUpload(DWORD crash_id); - - bool RequestDump(EXCEPTION_POINTERS* ex_info, - MDRawAssertionInfo* assert_info); - - // Requests the crash server to generate a dump with the given - // exception information. - // - // Returns true if the dump was successful; false otherwise. Note that - // if the registration step was not performed or it was not successful, - // false will be returned. - bool RequestDump(EXCEPTION_POINTERS* ex_info); - - // Requests the crash server to generate a dump with the given - // assertion information. - // - // Returns true if the dump was successful; false otherwise. Note that - // if the registration step was not performed or it was not successful, - // false will be returned. - bool RequestDump(MDRawAssertionInfo* assert_info); - - // If the crash generation client is running in a sandbox that prevents it - // from opening the named pipe directly, the server process may open the - // handle and duplicate it into the client process with this helper method. - // Returns INVALID_HANDLE_VALUE on failure. The process must have been opened - // with the PROCESS_DUP_HANDLE access right. - static HANDLE DuplicatePipeToClientProcess(const wchar_t* pipe_name, - HANDLE hProcess); - - private: - // Connects to the appropriate pipe and sets the pipe handle state. - // - // Returns the pipe handle if everything goes well; otherwise Returns NULL. - HANDLE ConnectToServer(); - - // Performs a handshake with the server over the given pipe which should be - // already connected to the server. - // - // Returns true if handshake with the server was successful; false otherwise. - bool RegisterClient(HANDLE pipe); - - // Validates the given server response. - bool ValidateResponse(const ProtocolMessage& msg) const; - - // Returns true if the registration step succeeded; false otherwise. - bool IsRegistered() const; - - // Connects to the given named pipe with given parameters. - // - // Returns true if the connection is successful; false otherwise. - HANDLE ConnectToPipe(const wchar_t* pipe_name, - DWORD pipe_access, - DWORD flags_attrs); - - // Signals the crash event and wait for the server to generate crash. - bool SignalCrashEventAndWait(); - - // Pipe name to use to talk to server. - std::wstring pipe_name_; - - // Pipe handle duplicated from server process. Only valid before - // Register is called. - HANDLE pipe_handle_; - - // Custom client information - CustomClientInfo custom_info_; - - // Type of dump to generate. - MINIDUMP_TYPE dump_type_; - - // Event to signal in case of a crash. - HANDLE crash_event_; - - // Handle to wait on after signaling a crash for the server - // to finish generating crash dump. - HANDLE crash_generated_; - - // Handle to a mutex that will become signaled with WAIT_ABANDONED - // if the server process goes down. - HANDLE server_alive_; - - // Server process id. - DWORD server_process_id_; - - // Id of the thread that caused the crash. - DWORD thread_id_; - - // Exception pointers for an exception crash. - EXCEPTION_POINTERS* exception_pointers_; - - // Assertion info for an invalid parameter or pure call crash. - MDRawAssertionInfo assert_info_; - - // Disable copy ctor and operator=. - CrashGenerationClient(const CrashGenerationClient& crash_client); - CrashGenerationClient& operator=(const CrashGenerationClient& crash_client); -}; - -} // namespace google_breakpad - -#endif // CLIENT_WINDOWS_CRASH_GENERATION_CRASH_GENERATION_CLIENT_H_ diff --git a/toolkit/crashreporter/google-breakpad/src/client/windows/crash_generation/crash_generation_server.cc b/toolkit/crashreporter/google-breakpad/src/client/windows/crash_generation/crash_generation_server.cc deleted file mode 100644 index bb0968fe0..000000000 --- a/toolkit/crashreporter/google-breakpad/src/client/windows/crash_generation/crash_generation_server.cc +++ /dev/null @@ -1,931 +0,0 @@ -// Copyright (c) 2008, 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 "client/windows/crash_generation/crash_generation_server.h" -#include <windows.h> -#include <cassert> -#include <list> -#include "client/windows/common/auto_critical_section.h" -#include "common/scoped_ptr.h" - -#include "client/windows/crash_generation/client_info.h" - -namespace google_breakpad { - -// Output buffer size. -static const size_t kOutBufferSize = 64; - -// Input buffer size. -static const size_t kInBufferSize = 64; - -// Access flags for the client on the dump request event. -static const DWORD kDumpRequestEventAccess = EVENT_MODIFY_STATE; - -// Access flags for the client on the dump generated event. -static const DWORD kDumpGeneratedEventAccess = EVENT_MODIFY_STATE | - SYNCHRONIZE; - -// Access flags for the client on the mutex. -static const DWORD kMutexAccess = SYNCHRONIZE; - -// Attribute flags for the pipe. -static const DWORD kPipeAttr = FILE_FLAG_FIRST_PIPE_INSTANCE | - PIPE_ACCESS_DUPLEX | - FILE_FLAG_OVERLAPPED; - -// Mode for the pipe. -static const DWORD kPipeMode = PIPE_TYPE_MESSAGE | - PIPE_READMODE_MESSAGE | - PIPE_WAIT; - -// For pipe I/O, execute the callback in the wait thread itself, -// since the callback does very little work. The callback executes -// the code for one of the states of the server state machine and -// the code for all of the states perform async I/O and hence -// finish very quickly. -static const ULONG kPipeIOThreadFlags = WT_EXECUTEINWAITTHREAD; - -// Dump request threads will, most likely, generate dumps. That may -// take some time to finish, so specify WT_EXECUTELONGFUNCTION flag. -static const ULONG kDumpRequestThreadFlags = WT_EXECUTEINWAITTHREAD | - WT_EXECUTELONGFUNCTION; - -static bool IsClientRequestValid(const ProtocolMessage& msg) { - return msg.tag == MESSAGE_TAG_UPLOAD_REQUEST || - (msg.tag == MESSAGE_TAG_REGISTRATION_REQUEST && - msg.id != 0 && - msg.thread_id != NULL && - msg.exception_pointers != NULL && - msg.assert_info != NULL); -} - -#ifndef NDEBUG -static bool CheckForIOIncomplete(bool success) { - // We should never get an I/O incomplete since we should not execute this - // unless the operation has finished and the overlapped event is signaled. If - // we do get INCOMPLETE, we have a bug in our code. - return success ? false : (GetLastError() == ERROR_IO_INCOMPLETE); -} -#endif - -CrashGenerationServer::CrashGenerationServer( - const std::wstring& pipe_name, - SECURITY_ATTRIBUTES* pipe_sec_attrs, - OnClientConnectedCallback connect_callback, - void* connect_context, - OnClientDumpRequestCallback dump_callback, - void* dump_context, - OnClientExitedCallback exit_callback, - void* exit_context, - OnClientUploadRequestCallback upload_request_callback, - void* upload_context, - bool generate_dumps, - const std::wstring* dump_path) - : pipe_name_(pipe_name), - pipe_sec_attrs_(pipe_sec_attrs), - pipe_(NULL), - pipe_wait_handle_(NULL), - server_alive_handle_(NULL), - connect_callback_(connect_callback), - connect_context_(connect_context), - dump_callback_(dump_callback), - dump_context_(dump_context), - exit_callback_(exit_callback), - exit_context_(exit_context), - upload_request_callback_(upload_request_callback), - upload_context_(upload_context), - generate_dumps_(generate_dumps), - pre_fetch_custom_info_(true), - dump_path_(dump_path ? *dump_path : L""), - server_state_(IPC_SERVER_STATE_UNINITIALIZED), - shutting_down_(false), - overlapped_(), - client_info_(NULL) { - InitializeCriticalSection(&sync_); -} - -// This should never be called from the OnPipeConnected callback. -// Otherwise the UnregisterWaitEx call below will cause a deadlock. -CrashGenerationServer::~CrashGenerationServer() { - // New scope to release the lock automatically. - { - // Make sure no clients are added or removed beyond this point. - // Before adding or removing any clients, the critical section - // must be entered and the shutting_down_ flag checked. The - // critical section is then exited only after the clients_ list - // modifications are done and the list is in a consistent state. - AutoCriticalSection lock(&sync_); - - // Indicate to existing threads that server is shutting down. - shutting_down_ = true; - } - // No one will modify the clients_ list beyond this point - - // not even from another thread. - - // Even if there are no current worker threads running, it is possible that - // an I/O request is pending on the pipe right now but not yet done. - // In fact, it's very likely this is the case unless we are in an ERROR - // state. If we don't wait for the pending I/O to be done, then when the I/O - // completes, it may write to invalid memory. AppVerifier will flag this - // problem too. So we disconnect from the pipe and then wait for the server - // to get into error state so that the pending I/O will fail and get - // cleared. - DisconnectNamedPipe(pipe_); - int num_tries = 100; - while (num_tries-- && server_state_ != IPC_SERVER_STATE_ERROR) { - Sleep(10); - } - - // Unregister wait on the pipe. - if (pipe_wait_handle_) { - // Wait for already executing callbacks to finish. - UnregisterWaitEx(pipe_wait_handle_, INVALID_HANDLE_VALUE); - } - - // Close the pipe to avoid further client connections. - if (pipe_) { - CloseHandle(pipe_); - } - - // Request all ClientInfo objects to unregister all waits. - // No need to enter the critical section because no one is allowed to modify - // the clients_ list once the shutting_down_ flag is set. - std::list<ClientInfo*>::iterator iter; - for (iter = clients_.begin(); iter != clients_.end(); ++iter) { - ClientInfo* client_info = *iter; - // Unregister waits. Wait for already executing callbacks to finish. - // Unregister the client process exit wait first and only then unregister - // the dump request wait. The reason is that the OnClientExit callback - // also unregisters the dump request wait and such a race (doing the same - // unregistration from two threads) is undesirable. - client_info->UnregisterProcessExitWait(true); - client_info->UnregisterDumpRequestWaitAndBlockUntilNoPending(); - - // Destroying the ClientInfo here is safe because all wait operations for - // this ClientInfo were unregistered and no pending or running callbacks - // for this ClientInfo can possible exist (block_until_no_pending option - // was used). - delete client_info; - } - - if (server_alive_handle_) { - // Release the mutex before closing the handle so that clients requesting - // dumps wait for a long time for the server to generate a dump. - ReleaseMutex(server_alive_handle_); - CloseHandle(server_alive_handle_); - } - - if (overlapped_.hEvent) { - CloseHandle(overlapped_.hEvent); - } - - DeleteCriticalSection(&sync_); -} - -bool CrashGenerationServer::Start() { - if (server_state_ != IPC_SERVER_STATE_UNINITIALIZED) { - return false; - } - - server_state_ = IPC_SERVER_STATE_INITIAL; - - server_alive_handle_ = CreateMutex(NULL, TRUE, NULL); - if (!server_alive_handle_) { - return false; - } - - // Event to signal the client connection and pipe reads and writes. - overlapped_.hEvent = CreateEvent(NULL, // Security descriptor. - TRUE, // Manual reset. - FALSE, // Initially nonsignaled. - NULL); // Name. - if (!overlapped_.hEvent) { - return false; - } - - // Register a callback with the thread pool for the client connection. - if (!RegisterWaitForSingleObject(&pipe_wait_handle_, - overlapped_.hEvent, - OnPipeConnected, - this, - INFINITE, - kPipeIOThreadFlags)) { - return false; - } - - pipe_ = CreateNamedPipe(pipe_name_.c_str(), - kPipeAttr, - kPipeMode, - 1, - kOutBufferSize, - kInBufferSize, - 0, - pipe_sec_attrs_); - if (pipe_ == INVALID_HANDLE_VALUE) { - return false; - } - - // Kick-start the state machine. This will initiate an asynchronous wait - // for client connections. - if (!SetEvent(overlapped_.hEvent)) { - server_state_ = IPC_SERVER_STATE_ERROR; - return false; - } - - // If we are in error state, it's because we failed to start listening. - return true; -} - -// If the server thread serving clients ever gets into the -// ERROR state, reset the event, close the pipe and remain -// in the error state forever. Error state means something -// that we didn't account for has happened, and it's dangerous -// to do anything unknowingly. -void CrashGenerationServer::HandleErrorState() { - assert(server_state_ == IPC_SERVER_STATE_ERROR); - - // If the server is shutting down anyway, don't clean up - // here since shut down process will clean up. - if (shutting_down_) { - return; - } - - if (pipe_wait_handle_) { - UnregisterWait(pipe_wait_handle_); - pipe_wait_handle_ = NULL; - } - - if (pipe_) { - CloseHandle(pipe_); - pipe_ = NULL; - } - - if (overlapped_.hEvent) { - CloseHandle(overlapped_.hEvent); - overlapped_.hEvent = NULL; - } -} - -// When the server thread serving clients is in the INITIAL state, -// try to connect to the pipe asynchronously. If the connection -// finishes synchronously, directly go into the CONNECTED state; -// otherwise go into the CONNECTING state. For any problems, go -// into the ERROR state. -void CrashGenerationServer::HandleInitialState() { - assert(server_state_ == IPC_SERVER_STATE_INITIAL); - - if (!ResetEvent(overlapped_.hEvent)) { - EnterErrorState(); - return; - } - - bool success = ConnectNamedPipe(pipe_, &overlapped_) != FALSE; - DWORD error_code = success ? ERROR_SUCCESS : GetLastError(); - - // From MSDN, it is not clear that when ConnectNamedPipe is used - // in an overlapped mode, will it ever return non-zero value, and - // if so, in what cases. - assert(!success); - - switch (error_code) { - case ERROR_IO_PENDING: - EnterStateWhenSignaled(IPC_SERVER_STATE_CONNECTING); - break; - - case ERROR_PIPE_CONNECTED: - EnterStateImmediately(IPC_SERVER_STATE_CONNECTED); - break; - - default: - EnterErrorState(); - break; - } -} - -// When the server thread serving the clients is in the CONNECTING state, -// try to get the result of the asynchronous connection request using -// the OVERLAPPED object. If the result indicates the connection is done, -// go into the CONNECTED state. If the result indicates I/O is still -// INCOMPLETE, remain in the CONNECTING state. For any problems, -// go into the DISCONNECTING state. -void CrashGenerationServer::HandleConnectingState() { - assert(server_state_ == IPC_SERVER_STATE_CONNECTING); - - DWORD bytes_count = 0; - bool success = GetOverlappedResult(pipe_, - &overlapped_, - &bytes_count, - FALSE) != FALSE; - DWORD error_code = success ? ERROR_SUCCESS : GetLastError(); - - if (success) { - EnterStateImmediately(IPC_SERVER_STATE_CONNECTED); - } else if (error_code != ERROR_IO_INCOMPLETE) { - EnterStateImmediately(IPC_SERVER_STATE_DISCONNECTING); - } else { - // remain in CONNECTING state - } -} - -// When the server thread serving the clients is in the CONNECTED state, -// try to issue an asynchronous read from the pipe. If read completes -// synchronously or if I/O is pending then go into the READING state. -// For any problems, go into the DISCONNECTING state. -void CrashGenerationServer::HandleConnectedState() { - assert(server_state_ == IPC_SERVER_STATE_CONNECTED); - - DWORD bytes_count = 0; - memset(&msg_, 0, sizeof(msg_)); - bool success = ReadFile(pipe_, - &msg_, - sizeof(msg_), - &bytes_count, - &overlapped_) != FALSE; - DWORD error_code = success ? ERROR_SUCCESS : GetLastError(); - - // Note that the asynchronous read issued above can finish before the - // code below executes. But, it is okay to change state after issuing - // the asynchronous read. This is because even if the asynchronous read - // is done, the callback for it would not be executed until the current - // thread finishes its execution. - if (success || error_code == ERROR_IO_PENDING) { - EnterStateWhenSignaled(IPC_SERVER_STATE_READING); - } else { - EnterStateImmediately(IPC_SERVER_STATE_DISCONNECTING); - } -} - -// When the server thread serving the clients is in the READING state, -// try to get the result of the async read. If async read is done, -// go into the READ_DONE state. For any problems, go into the -// DISCONNECTING state. -void CrashGenerationServer::HandleReadingState() { - assert(server_state_ == IPC_SERVER_STATE_READING); - - DWORD bytes_count = 0; - bool success = GetOverlappedResult(pipe_, - &overlapped_, - &bytes_count, - FALSE) != FALSE; - if (success && bytes_count == sizeof(ProtocolMessage)) { - EnterStateImmediately(IPC_SERVER_STATE_READ_DONE); - return; - } - - assert(!CheckForIOIncomplete(success)); - EnterStateImmediately(IPC_SERVER_STATE_DISCONNECTING); -} - -// When the server thread serving the client is in the READ_DONE state, -// validate the client's request message, register the client by -// creating appropriate objects and prepare the response. Then try to -// write the response to the pipe asynchronously. If that succeeds, -// go into the WRITING state. For any problems, go into the DISCONNECTING -// state. -void CrashGenerationServer::HandleReadDoneState() { - assert(server_state_ == IPC_SERVER_STATE_READ_DONE); - - if (!IsClientRequestValid(msg_)) { - EnterStateImmediately(IPC_SERVER_STATE_DISCONNECTING); - return; - } - - if (msg_.tag == MESSAGE_TAG_UPLOAD_REQUEST) { - if (upload_request_callback_) - upload_request_callback_(upload_context_, msg_.id); - EnterStateImmediately(IPC_SERVER_STATE_DISCONNECTING); - return; - } - - scoped_ptr<ClientInfo> client_info( - new ClientInfo(this, - msg_.id, - msg_.dump_type, - msg_.thread_id, - msg_.exception_pointers, - msg_.assert_info, - msg_.custom_client_info)); - - if (!client_info->Initialize()) { - EnterStateImmediately(IPC_SERVER_STATE_DISCONNECTING); - return; - } - - // Issues an asynchronous WriteFile call if successful. - // Iff successful, assigns ownership of the client_info pointer to the server - // instance, in which case we must be sure not to free it in this function. - if (!RespondToClient(client_info.get())) { - EnterStateImmediately(IPC_SERVER_STATE_DISCONNECTING); - return; - } - - // This is only valid as long as it can be found in the clients_ list - client_info_ = client_info.release(); - - // Note that the asynchronous write issued by RespondToClient function - // can finish before the code below executes. But it is okay to change - // state after issuing the asynchronous write. This is because even if - // the asynchronous write is done, the callback for it would not be - // executed until the current thread finishes its execution. - EnterStateWhenSignaled(IPC_SERVER_STATE_WRITING); -} - -// When the server thread serving the clients is in the WRITING state, -// try to get the result of the async write. If the async write is done, -// go into the WRITE_DONE state. For any problems, go into the -// DISONNECTING state. -void CrashGenerationServer::HandleWritingState() { - assert(server_state_ == IPC_SERVER_STATE_WRITING); - - DWORD bytes_count = 0; - bool success = GetOverlappedResult(pipe_, - &overlapped_, - &bytes_count, - FALSE) != FALSE; - if (success) { - EnterStateImmediately(IPC_SERVER_STATE_WRITE_DONE); - return; - } - - assert(!CheckForIOIncomplete(success)); - EnterStateImmediately(IPC_SERVER_STATE_DISCONNECTING); -} - -// When the server thread serving the clients is in the WRITE_DONE state, -// try to issue an async read on the pipe. If the read completes synchronously -// or if I/O is still pending then go into the READING_ACK state. For any -// issues, go into the DISCONNECTING state. -void CrashGenerationServer::HandleWriteDoneState() { - assert(server_state_ == IPC_SERVER_STATE_WRITE_DONE); - - DWORD bytes_count = 0; - bool success = ReadFile(pipe_, - &msg_, - sizeof(msg_), - &bytes_count, - &overlapped_) != FALSE; - DWORD error_code = success ? ERROR_SUCCESS : GetLastError(); - - if (success) { - EnterStateImmediately(IPC_SERVER_STATE_READING_ACK); - } else if (error_code == ERROR_IO_PENDING) { - EnterStateWhenSignaled(IPC_SERVER_STATE_READING_ACK); - } else { - EnterStateImmediately(IPC_SERVER_STATE_DISCONNECTING); - } -} - -// When the server thread serving the clients is in the READING_ACK state, -// try to get result of async read. Go into the DISCONNECTING state. -void CrashGenerationServer::HandleReadingAckState() { - assert(server_state_ == IPC_SERVER_STATE_READING_ACK); - - DWORD bytes_count = 0; - bool success = GetOverlappedResult(pipe_, - &overlapped_, - &bytes_count, - FALSE) != FALSE; - if (success) { - // The connection handshake with the client is now complete; perform - // the callback. - if (connect_callback_) { - // Note that there is only a single copy of the ClientInfo of the - // currently connected client. However it is being referenced from - // two different places: - // - the client_info_ member - // - the clients_ list - // The lifetime of this ClientInfo depends on the lifetime of the - // client process - basically it can go away at any time. - // However, as long as it is referenced by the clients_ list it - // is guaranteed to be valid. Enter the critical section and check - // to see whether the client_info_ can be found in the list. - // If found, execute the callback and only then leave the critical - // section. - AutoCriticalSection lock(&sync_); - - bool client_is_still_alive = false; - std::list<ClientInfo*>::iterator iter; - for (iter = clients_.begin(); iter != clients_.end(); ++iter) { - if (client_info_ == *iter) { - client_is_still_alive = true; - break; - } - } - - if (client_is_still_alive) { - connect_callback_(connect_context_, client_info_); - } - } - } else { - assert(!CheckForIOIncomplete(success)); - } - - EnterStateImmediately(IPC_SERVER_STATE_DISCONNECTING); -} - -// When the server thread serving the client is in the DISCONNECTING state, -// disconnect from the pipe and reset the event. If anything fails, go into -// the ERROR state. If it goes well, go into the INITIAL state and set the -// event to start all over again. -void CrashGenerationServer::HandleDisconnectingState() { - assert(server_state_ == IPC_SERVER_STATE_DISCONNECTING); - - // Done serving the client. - client_info_ = NULL; - - overlapped_.Internal = NULL; - overlapped_.InternalHigh = NULL; - overlapped_.Offset = 0; - overlapped_.OffsetHigh = 0; - overlapped_.Pointer = NULL; - - if (!ResetEvent(overlapped_.hEvent)) { - EnterErrorState(); - return; - } - - if (!DisconnectNamedPipe(pipe_)) { - EnterErrorState(); - return; - } - - // If the server is shutting down do not connect to the - // next client. - if (shutting_down_) { - return; - } - - EnterStateImmediately(IPC_SERVER_STATE_INITIAL); -} - -void CrashGenerationServer::EnterErrorState() { - SetEvent(overlapped_.hEvent); - server_state_ = IPC_SERVER_STATE_ERROR; -} - -void CrashGenerationServer::EnterStateWhenSignaled(IPCServerState state) { - server_state_ = state; -} - -void CrashGenerationServer::EnterStateImmediately(IPCServerState state) { - server_state_ = state; - - if (!SetEvent(overlapped_.hEvent)) { - server_state_ = IPC_SERVER_STATE_ERROR; - } -} - -bool CrashGenerationServer::PrepareReply(const ClientInfo& client_info, - ProtocolMessage* reply) const { - reply->tag = MESSAGE_TAG_REGISTRATION_RESPONSE; - reply->id = GetCurrentProcessId(); - - if (CreateClientHandles(client_info, reply)) { - return true; - } - - // Closing of remote handles (belonging to a different process) can - // only be done through DuplicateHandle. - if (reply->dump_request_handle) { - DuplicateHandle(client_info.process_handle(), // hSourceProcessHandle - reply->dump_request_handle, // hSourceHandle - NULL, // hTargetProcessHandle - 0, // lpTargetHandle - 0, // dwDesiredAccess - FALSE, // bInheritHandle - DUPLICATE_CLOSE_SOURCE); // dwOptions - reply->dump_request_handle = NULL; - } - - if (reply->dump_generated_handle) { - DuplicateHandle(client_info.process_handle(), // hSourceProcessHandle - reply->dump_generated_handle, // hSourceHandle - NULL, // hTargetProcessHandle - 0, // lpTargetHandle - 0, // dwDesiredAccess - FALSE, // bInheritHandle - DUPLICATE_CLOSE_SOURCE); // dwOptions - reply->dump_generated_handle = NULL; - } - - if (reply->server_alive_handle) { - DuplicateHandle(client_info.process_handle(), // hSourceProcessHandle - reply->server_alive_handle, // hSourceHandle - NULL, // hTargetProcessHandle - 0, // lpTargetHandle - 0, // dwDesiredAccess - FALSE, // bInheritHandle - DUPLICATE_CLOSE_SOURCE); // dwOptions - reply->server_alive_handle = NULL; - } - - return false; -} - -bool CrashGenerationServer::CreateClientHandles(const ClientInfo& client_info, - ProtocolMessage* reply) const { - HANDLE current_process = GetCurrentProcess(); - if (!DuplicateHandle(current_process, - client_info.dump_requested_handle(), - client_info.process_handle(), - &reply->dump_request_handle, - kDumpRequestEventAccess, - FALSE, - 0)) { - return false; - } - - if (!DuplicateHandle(current_process, - client_info.dump_generated_handle(), - client_info.process_handle(), - &reply->dump_generated_handle, - kDumpGeneratedEventAccess, - FALSE, - 0)) { - return false; - } - - if (!DuplicateHandle(current_process, - server_alive_handle_, - client_info.process_handle(), - &reply->server_alive_handle, - kMutexAccess, - FALSE, - 0)) { - return false; - } - - return true; -} - -bool CrashGenerationServer::RespondToClient(ClientInfo* client_info) { - ProtocolMessage reply; - if (!PrepareReply(*client_info, &reply)) { - return false; - } - - DWORD bytes_count = 0; - bool success = WriteFile(pipe_, - &reply, - sizeof(reply), - &bytes_count, - &overlapped_) != FALSE; - DWORD error_code = success ? ERROR_SUCCESS : GetLastError(); - - if (!success && error_code != ERROR_IO_PENDING) { - return false; - } - - // Takes over ownership of client_info. We MUST return true if AddClient - // succeeds. - return AddClient(client_info); -} - -// The server thread servicing the clients runs this method. The method -// implements the state machine described in ReadMe.txt along with the -// helper methods HandleXXXState. -void CrashGenerationServer::HandleConnectionRequest() { - // If the server is shutting down, get into ERROR state, reset the event so - // more workers don't run and return immediately. - if (shutting_down_) { - server_state_ = IPC_SERVER_STATE_ERROR; - ResetEvent(overlapped_.hEvent); - return; - } - - switch (server_state_) { - case IPC_SERVER_STATE_ERROR: - HandleErrorState(); - break; - - case IPC_SERVER_STATE_INITIAL: - HandleInitialState(); - break; - - case IPC_SERVER_STATE_CONNECTING: - HandleConnectingState(); - break; - - case IPC_SERVER_STATE_CONNECTED: - HandleConnectedState(); - break; - - case IPC_SERVER_STATE_READING: - HandleReadingState(); - break; - - case IPC_SERVER_STATE_READ_DONE: - HandleReadDoneState(); - break; - - case IPC_SERVER_STATE_WRITING: - HandleWritingState(); - break; - - case IPC_SERVER_STATE_WRITE_DONE: - HandleWriteDoneState(); - break; - - case IPC_SERVER_STATE_READING_ACK: - HandleReadingAckState(); - break; - - case IPC_SERVER_STATE_DISCONNECTING: - HandleDisconnectingState(); - break; - - default: - assert(false); - // This indicates that we added one more state without - // adding handling code. - server_state_ = IPC_SERVER_STATE_ERROR; - break; - } -} - -bool CrashGenerationServer::AddClient(ClientInfo* client_info) { - HANDLE request_wait_handle = NULL; - if (!RegisterWaitForSingleObject(&request_wait_handle, - client_info->dump_requested_handle(), - OnDumpRequest, - client_info, - INFINITE, - kDumpRequestThreadFlags)) { - return false; - } - - client_info->set_dump_request_wait_handle(request_wait_handle); - - // OnClientEnd will be called when the client process terminates. - HANDLE process_wait_handle = NULL; - if (!RegisterWaitForSingleObject(&process_wait_handle, - client_info->process_handle(), - OnClientEnd, - client_info, - INFINITE, - WT_EXECUTEONLYONCE)) { - return false; - } - - client_info->set_process_exit_wait_handle(process_wait_handle); - - // New scope to hold the lock for the shortest time. - { - AutoCriticalSection lock(&sync_); - if (shutting_down_) { - // If server is shutting down, don't add new clients - return false; - } - clients_.push_back(client_info); - } - - return true; -} - -// static -void CALLBACK CrashGenerationServer::OnPipeConnected(void* context, BOOLEAN) { - assert(context); - - CrashGenerationServer* obj = - reinterpret_cast<CrashGenerationServer*>(context); - obj->HandleConnectionRequest(); -} - -// static -void CALLBACK CrashGenerationServer::OnDumpRequest(void* context, BOOLEAN) { - assert(context); - ClientInfo* client_info = reinterpret_cast<ClientInfo*>(context); - - CrashGenerationServer* crash_server = client_info->crash_server(); - assert(crash_server); - if (crash_server->pre_fetch_custom_info_) { - client_info->PopulateCustomInfo(); - } - crash_server->HandleDumpRequest(*client_info); - - ResetEvent(client_info->dump_requested_handle()); -} - -// static -void CALLBACK CrashGenerationServer::OnClientEnd(void* context, BOOLEAN) { - assert(context); - ClientInfo* client_info = reinterpret_cast<ClientInfo*>(context); - - CrashGenerationServer* crash_server = client_info->crash_server(); - assert(crash_server); - - crash_server->HandleClientProcessExit(client_info); -} - -void CrashGenerationServer::HandleClientProcessExit(ClientInfo* client_info) { - assert(client_info); - - // Must unregister the dump request wait operation and wait for any - // dump requests that might be pending to finish before proceeding - // with the client_info cleanup. - client_info->UnregisterDumpRequestWaitAndBlockUntilNoPending(); - - if (exit_callback_) { - exit_callback_(exit_context_, client_info); - } - - // Start a new scope to release lock automatically. - { - AutoCriticalSection lock(&sync_); - if (shutting_down_) { - // The crash generation server is shutting down and as part of the - // shutdown process it will delete all clients from the clients_ list. - return; - } - clients_.remove(client_info); - } - - // Explicitly unregister the process exit wait using the non-blocking method. - // Otherwise, the destructor will attempt to unregister it using the blocking - // method which will lead to a deadlock because it is being called from the - // callback of the same wait operation - client_info->UnregisterProcessExitWait(false); - - delete client_info; -} - -void CrashGenerationServer::HandleDumpRequest(const ClientInfo& client_info) { - bool execute_callback = true; - // Generate the dump only if it's explicitly requested by the - // server application; otherwise the server might want to generate - // dump in the callback. - std::wstring dump_path; - if (generate_dumps_) { - if (!GenerateDump(client_info, &dump_path)) { - // client proccess terminated or some other error - execute_callback = false; - } - } - - if (dump_callback_ && execute_callback) { - std::wstring* ptr_dump_path = (dump_path == L"") ? NULL : &dump_path; - dump_callback_(dump_context_, &client_info, ptr_dump_path); - } - - SetEvent(client_info.dump_generated_handle()); -} - -bool CrashGenerationServer::GenerateDump(const ClientInfo& client, - std::wstring* dump_path) { - assert(client.pid() != 0); - assert(client.process_handle()); - - // We have to get the address of EXCEPTION_INFORMATION from - // the client process address space. - EXCEPTION_POINTERS* client_ex_info = NULL; - if (!client.GetClientExceptionInfo(&client_ex_info)) { - return false; - } - - DWORD client_thread_id = 0; - if (!client.GetClientThreadId(&client_thread_id)) { - return false; - } - - MinidumpGenerator dump_generator(dump_path_, - client.process_handle(), - client.pid(), - client_thread_id, - GetCurrentThreadId(), - client_ex_info, - client.assert_info(), - client.dump_type(), - true); - if (!dump_generator.GenerateDumpFile(dump_path)) { - return false; - } - return dump_generator.WriteMinidump(); -} - -} // namespace google_breakpad diff --git a/toolkit/crashreporter/google-breakpad/src/client/windows/crash_generation/crash_generation_server.h b/toolkit/crashreporter/google-breakpad/src/client/windows/crash_generation/crash_generation_server.h deleted file mode 100644 index 0ea90e510..000000000 --- a/toolkit/crashreporter/google-breakpad/src/client/windows/crash_generation/crash_generation_server.h +++ /dev/null @@ -1,299 +0,0 @@ -// Copyright (c) 2008, 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. - -#ifndef CLIENT_WINDOWS_CRASH_GENERATION_CRASH_GENERATION_SERVER_H__ -#define CLIENT_WINDOWS_CRASH_GENERATION_CRASH_GENERATION_SERVER_H__ - -#include <list> -#include <string> -#include "client/windows/common/ipc_protocol.h" -#include "client/windows/crash_generation/minidump_generator.h" -#include "common/scoped_ptr.h" - -namespace google_breakpad { -class ClientInfo; - -// Abstraction for server side implementation of out-of-process crash -// generation protocol for Windows platform only. It generates Windows -// minidump files for client processes that request dump generation. When -// the server is requested to start listening for clients (by calling the -// Start method), it creates a named pipe and waits for the clients to -// register. In response, it hands them event handles that the client can -// signal to request dump generation. When the clients request dump -// generation in this way, the server generates Windows minidump files. -class CrashGenerationServer { - public: - typedef void (*OnClientConnectedCallback)(void* context, - const ClientInfo* client_info); - - typedef void (*OnClientDumpRequestCallback)(void* context, - const ClientInfo* client_info, - const std::wstring* file_path); - - typedef void (*OnClientExitedCallback)(void* context, - const ClientInfo* client_info); - - typedef void (*OnClientUploadRequestCallback)(void* context, - const DWORD crash_id); - - // Creates an instance with the given parameters. - // - // Parameter pipe_name: Name of the Windows named pipe - // Parameter pipe_sec_attrs Security attributes to set on the pipe. Pass - // NULL to use default security on the pipe. By default, the pipe created - // allows Local System, Administrators and the Creator full control and - // the Everyone group read access on the pipe. - // Parameter connect_callback: Callback for a new client connection. - // Parameter connect_context: Context for client connection callback. - // Parameter crash_callback: Callback for a client crash dump request. - // Parameter crash_context: Context for client crash dump request callback. - // Parameter exit_callback: Callback for client process exit. - // Parameter exit_context: Context for client exit callback. - // Parameter generate_dumps: Whether to automatically generate dumps. - // Client code of this class might want to generate dumps explicitly in the - // crash dump request callback. In that case, false can be passed for this - // parameter. - // Parameter dump_path: Path for generating dumps; required only if true is - // passed for generateDumps parameter; NULL can be passed otherwise. - CrashGenerationServer(const std::wstring& pipe_name, - SECURITY_ATTRIBUTES* pipe_sec_attrs, - OnClientConnectedCallback connect_callback, - void* connect_context, - OnClientDumpRequestCallback dump_callback, - void* dump_context, - OnClientExitedCallback exit_callback, - void* exit_context, - OnClientUploadRequestCallback upload_request_callback, - void* upload_context, - bool generate_dumps, - const std::wstring* dump_path); - - ~CrashGenerationServer(); - - // Performs initialization steps needed to start listening to clients. Upon - // successful return clients may connect to this server's pipe. - // - // Returns true if initialization is successful; false otherwise. - bool Start(); - - void pre_fetch_custom_info(bool do_pre_fetch) { - pre_fetch_custom_info_ = do_pre_fetch; - } - - private: - // Various states the client can be in during the handshake with - // the server. - enum IPCServerState { - // Server starts in this state. - IPC_SERVER_STATE_UNINITIALIZED, - - // Server is in error state and it cannot serve any clients. - IPC_SERVER_STATE_ERROR, - - // Server starts in this state. - IPC_SERVER_STATE_INITIAL, - - // Server has issued an async connect to the pipe and it is waiting - // for the connection to be established. - IPC_SERVER_STATE_CONNECTING, - - // Server is connected successfully. - IPC_SERVER_STATE_CONNECTED, - - // Server has issued an async read from the pipe and it is waiting for - // the read to finish. - IPC_SERVER_STATE_READING, - - // Server is done reading from the pipe. - IPC_SERVER_STATE_READ_DONE, - - // Server has issued an async write to the pipe and it is waiting for - // the write to finish. - IPC_SERVER_STATE_WRITING, - - // Server is done writing to the pipe. - IPC_SERVER_STATE_WRITE_DONE, - - // Server has issued an async read from the pipe for an ack and it - // is waiting for the read to finish. - IPC_SERVER_STATE_READING_ACK, - - // Server is done writing to the pipe and it is now ready to disconnect - // and reconnect. - IPC_SERVER_STATE_DISCONNECTING - }; - - // - // Helper methods to handle various server IPC states. - // - void HandleErrorState(); - void HandleInitialState(); - void HandleConnectingState(); - void HandleConnectedState(); - void HandleReadingState(); - void HandleReadDoneState(); - void HandleWritingState(); - void HandleWriteDoneState(); - void HandleReadingAckState(); - void HandleDisconnectingState(); - - // Prepares reply for a client from the given parameters. - bool PrepareReply(const ClientInfo& client_info, - ProtocolMessage* reply) const; - - // Duplicates various handles in the ClientInfo object for the client - // process and stores them in the given ProtocolMessage instance. If - // creating any handle fails, ProtocolMessage will contain the handles - // already created successfully, which should be closed by the caller. - bool CreateClientHandles(const ClientInfo& client_info, - ProtocolMessage* reply) const; - - // Response to the given client. Return true if all steps of - // responding to the client succeed, false otherwise. - bool RespondToClient(ClientInfo* client_info); - - // Handles a connection request from the client. - void HandleConnectionRequest(); - - // Handles a dump request from the client. - void HandleDumpRequest(const ClientInfo& client_info); - - // Callback for pipe connected event. - static void CALLBACK OnPipeConnected(void* context, BOOLEAN timer_or_wait); - - // Callback for a dump request. - static void CALLBACK OnDumpRequest(void* context, BOOLEAN timer_or_wait); - - // Callback for client process exit event. - static void CALLBACK OnClientEnd(void* context, BOOLEAN timer_or_wait); - - // Handles client process exit. - void HandleClientProcessExit(ClientInfo* client_info); - - // Adds the given client to the list of registered clients. - bool AddClient(ClientInfo* client_info); - - // Generates dump for the given client. - bool GenerateDump(const ClientInfo& client, std::wstring* dump_path); - - // Puts the server in a permanent error state and sets a signal such that - // the state will be immediately entered after the current state transition - // is complete. - void EnterErrorState(); - - // Puts the server in the specified state and sets a signal such that the - // state is immediately entered after the current state transition is - // complete. - void EnterStateImmediately(IPCServerState state); - - // Puts the server in the specified state. No signal will be set, so the state - // transition will only occur when signaled manually or by completion of an - // asynchronous IO operation. - void EnterStateWhenSignaled(IPCServerState state); - - // Sync object for thread-safe access to the shared list of clients. - CRITICAL_SECTION sync_; - - // List of clients. - std::list<ClientInfo*> clients_; - - // Pipe name. - std::wstring pipe_name_; - - // Pipe security attributes - SECURITY_ATTRIBUTES* pipe_sec_attrs_; - - // Handle to the pipe used for handshake with clients. - HANDLE pipe_; - - // Pipe wait handle. - HANDLE pipe_wait_handle_; - - // Handle to server-alive mutex. - HANDLE server_alive_handle_; - - // Callback for a successful client connection. - OnClientConnectedCallback connect_callback_; - - // Context for client connected callback. - void* connect_context_; - - // Callback for a client dump request. - OnClientDumpRequestCallback dump_callback_; - - // Context for client dump request callback. - void* dump_context_; - - // Callback for client process exit. - OnClientExitedCallback exit_callback_; - - // Context for client process exit callback. - void* exit_context_; - - // Callback for upload request. - OnClientUploadRequestCallback upload_request_callback_; - - // Context for upload request callback. - void* upload_context_; - - // Whether to generate dumps. - bool generate_dumps_; - - // Wether to populate custom information up-front. - bool pre_fetch_custom_info_; - - // The dump path for the server. - const std::wstring dump_path_; - - // State of the server in performing the IPC with the client. - // Note that since we restrict the pipe to one instance, we - // only need to keep one state of the server. Otherwise, server - // would have one state per client it is talking to. - IPCServerState server_state_; - - // Whether the server is shutting down. - bool shutting_down_; - - // Overlapped instance for async I/O on the pipe. - OVERLAPPED overlapped_; - - // Message object used in IPC with the client. - ProtocolMessage msg_; - - // Client Info for the client that's connecting to the server. - ClientInfo* client_info_; - - // Disable copy ctor and operator=. - CrashGenerationServer(const CrashGenerationServer& crash_server); - CrashGenerationServer& operator=(const CrashGenerationServer& crash_server); -}; - -} // namespace google_breakpad - -#endif // CLIENT_WINDOWS_CRASH_GENERATION_CRASH_GENERATION_SERVER_H__ diff --git a/toolkit/crashreporter/google-breakpad/src/client/windows/crash_generation/minidump_generator.cc b/toolkit/crashreporter/google-breakpad/src/client/windows/crash_generation/minidump_generator.cc deleted file mode 100644 index 786c9b937..000000000 --- a/toolkit/crashreporter/google-breakpad/src/client/windows/crash_generation/minidump_generator.cc +++ /dev/null @@ -1,579 +0,0 @@ -// Copyright (c) 2008, 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 "client/windows/crash_generation/minidump_generator.h" - -#include <assert.h> -#include <avrfsdk.h> - -#include <algorithm> -#include <iterator> -#include <list> -#include <vector> - -#include "client/windows/common/auto_critical_section.h" -#include "common/scoped_ptr.h" -#include "common/windows/guid_string.h" - -using std::wstring; - -namespace { - -// A helper class used to collect handle operations data. Unlike -// |MiniDumpWithHandleData| it records the operations for a single handle value -// only, making it possible to include this information to a minidump. -class HandleTraceData { - public: - HandleTraceData(); - ~HandleTraceData(); - - // Collects the handle operations data and formats a user stream to be added - // to the minidump. - bool CollectHandleData(HANDLE process_handle, - EXCEPTION_POINTERS* exception_pointers); - - // Fills the user dump entry with a pointer to the collected handle operations - // data. Returns |true| if the entry was initialized successfully, or |false| - // if no trace data is available. - bool GetUserStream(MINIDUMP_USER_STREAM* user_stream); - - private: - // Reads the exception code from the client process's address space. - // This routine assumes that the client process's pointer width matches ours. - static bool ReadExceptionCode(HANDLE process_handle, - EXCEPTION_POINTERS* exception_pointers, - DWORD* exception_code); - - // Stores handle operations retrieved by VerifierEnumerateResource(). - static ULONG CALLBACK RecordHandleOperations(void* resource_description, - void* enumeration_context, - ULONG* enumeration_level); - - // Function pointer type for VerifierEnumerateResource, which is looked up - // dynamically. - typedef BOOL (WINAPI* VerifierEnumerateResourceType)( - HANDLE Process, - ULONG Flags, - ULONG ResourceType, - AVRF_RESOURCE_ENUMERATE_CALLBACK ResourceCallback, - PVOID EnumerationContext); - - // Handle to dynamically loaded verifier.dll. - HMODULE verifier_module_; - - // Pointer to the VerifierEnumerateResource function. - VerifierEnumerateResourceType enumerate_resource_; - - // Handle value to look for. - ULONG64 handle_; - - // List of handle operations for |handle_|. - std::list<AVRF_HANDLE_OPERATION> operations_; - - // Minidump stream data. - std::vector<char> stream_; -}; - -HandleTraceData::HandleTraceData() - : verifier_module_(NULL), - enumerate_resource_(NULL), - handle_(NULL) { -} - -HandleTraceData::~HandleTraceData() { - if (verifier_module_) { - FreeLibrary(verifier_module_); - } -} - -bool HandleTraceData::CollectHandleData( - HANDLE process_handle, - EXCEPTION_POINTERS* exception_pointers) { - DWORD exception_code; - if (!ReadExceptionCode(process_handle, exception_pointers, &exception_code)) { - return false; - } - - // Verify whether the execption is STATUS_INVALID_HANDLE. Do not record any - // handle information if it is a different exception to keep the minidump - // small. - if (exception_code != STATUS_INVALID_HANDLE) { - return true; - } - - // Load verifier!VerifierEnumerateResource() dynamically. - verifier_module_ = LoadLibrary(TEXT("verifier.dll")); - if (!verifier_module_) { - return false; - } - - enumerate_resource_ = reinterpret_cast<VerifierEnumerateResourceType>( - GetProcAddress(verifier_module_, "VerifierEnumerateResource")); - if (!enumerate_resource_) { - return false; - } - - // STATUS_INVALID_HANDLE does not provide the offending handle value in - // the exception parameters so we have to guess. At the moment we scan - // the handle operations trace looking for the last invalid handle operation - // and record only the operations for that handle value. - if (enumerate_resource_(process_handle, - 0, - AvrfResourceHandleTrace, - &RecordHandleOperations, - this) != ERROR_SUCCESS) { - // The handle tracing must have not been enabled. - return true; - } - - // Now that |handle_| is initialized, purge all irrelevant operations. - std::list<AVRF_HANDLE_OPERATION>::iterator i = operations_.begin(); - std::list<AVRF_HANDLE_OPERATION>::iterator i_end = operations_.end(); - while (i != i_end) { - if (i->Handle == handle_) { - ++i; - } else { - i = operations_.erase(i); - } - } - - // Convert the list of recorded operations to a minidump stream. - stream_.resize(sizeof(MINIDUMP_HANDLE_OPERATION_LIST) + - sizeof(AVRF_HANDLE_OPERATION) * operations_.size()); - - MINIDUMP_HANDLE_OPERATION_LIST* stream_data = - reinterpret_cast<MINIDUMP_HANDLE_OPERATION_LIST*>( - &stream_.front()); - stream_data->SizeOfHeader = sizeof(MINIDUMP_HANDLE_OPERATION_LIST); - stream_data->SizeOfEntry = sizeof(AVRF_HANDLE_OPERATION); - stream_data->NumberOfEntries = static_cast<ULONG32>(operations_.size()); - stream_data->Reserved = 0; - std::copy(operations_.begin(), - operations_.end(), -#ifdef _MSC_VER - stdext::checked_array_iterator<AVRF_HANDLE_OPERATION*>( - reinterpret_cast<AVRF_HANDLE_OPERATION*>(stream_data + 1), - operations_.size()) -#else - reinterpret_cast<AVRF_HANDLE_OPERATION*>(stream_data + 1) -#endif - ); - - return true; -} - -bool HandleTraceData::GetUserStream(MINIDUMP_USER_STREAM* user_stream) { - if (stream_.empty()) { - return false; - } else { - user_stream->Type = HandleOperationListStream; - user_stream->BufferSize = static_cast<ULONG>(stream_.size()); - user_stream->Buffer = &stream_.front(); - return true; - } -} - -bool HandleTraceData::ReadExceptionCode( - HANDLE process_handle, - EXCEPTION_POINTERS* exception_pointers, - DWORD* exception_code) { - EXCEPTION_POINTERS pointers; - if (!ReadProcessMemory(process_handle, - exception_pointers, - &pointers, - sizeof(pointers), - NULL)) { - return false; - } - - if (!ReadProcessMemory(process_handle, - pointers.ExceptionRecord, - exception_code, - sizeof(*exception_code), - NULL)) { - return false; - } - - return true; -} - -ULONG CALLBACK HandleTraceData::RecordHandleOperations( - void* resource_description, - void* enumeration_context, - ULONG* enumeration_level) { - AVRF_HANDLE_OPERATION* description = - reinterpret_cast<AVRF_HANDLE_OPERATION*>(resource_description); - HandleTraceData* self = - reinterpret_cast<HandleTraceData*>(enumeration_context); - - // Remember the last invalid handle operation. - if (description->OperationType == OperationDbBADREF) { - self->handle_ = description->Handle; - } - - // Record all handle operations. - self->operations_.push_back(*description); - - *enumeration_level = HeapEnumerationEverything; - return ERROR_SUCCESS; -} - -} // namespace - -namespace google_breakpad { - -MinidumpGenerator::MinidumpGenerator( - const std::wstring& dump_path, - const HANDLE process_handle, - const DWORD process_id, - const DWORD thread_id, - const DWORD requesting_thread_id, - EXCEPTION_POINTERS* exception_pointers, - MDRawAssertionInfo* assert_info, - const MINIDUMP_TYPE dump_type, - const bool is_client_pointers) - : dbghelp_module_(NULL), - write_dump_(NULL), - rpcrt4_module_(NULL), - create_uuid_(NULL), - process_handle_(process_handle), - process_id_(process_id), - thread_id_(thread_id), - requesting_thread_id_(requesting_thread_id), - exception_pointers_(exception_pointers), - assert_info_(assert_info), - dump_type_(dump_type), - is_client_pointers_(is_client_pointers), - dump_path_(dump_path), - dump_file_(INVALID_HANDLE_VALUE), - full_dump_file_(INVALID_HANDLE_VALUE), - dump_file_is_internal_(false), - full_dump_file_is_internal_(false), - additional_streams_(NULL), - callback_info_(NULL) { - InitializeCriticalSection(&module_load_sync_); - InitializeCriticalSection(&get_proc_address_sync_); -} - -MinidumpGenerator::~MinidumpGenerator() { - if (dump_file_is_internal_ && dump_file_ != INVALID_HANDLE_VALUE) { - CloseHandle(dump_file_); - } - - if (full_dump_file_is_internal_ && full_dump_file_ != INVALID_HANDLE_VALUE) { - CloseHandle(full_dump_file_); - } - - if (dbghelp_module_) { - FreeLibrary(dbghelp_module_); - } - - if (rpcrt4_module_) { - FreeLibrary(rpcrt4_module_); - } - - DeleteCriticalSection(&get_proc_address_sync_); - DeleteCriticalSection(&module_load_sync_); -} - -bool MinidumpGenerator::WriteMinidump() { - bool full_memory_dump = (dump_type_ & MiniDumpWithFullMemory) != 0; - if (dump_file_ == INVALID_HANDLE_VALUE || - (full_memory_dump && full_dump_file_ == INVALID_HANDLE_VALUE)) { - return false; - } - - MiniDumpWriteDumpType write_dump = GetWriteDump(); - if (!write_dump) { - return false; - } - - MINIDUMP_EXCEPTION_INFORMATION* dump_exception_pointers = NULL; - MINIDUMP_EXCEPTION_INFORMATION dump_exception_info; - - // Setup the exception information object only if it's a dump - // due to an exception. - if (exception_pointers_) { - dump_exception_pointers = &dump_exception_info; - dump_exception_info.ThreadId = thread_id_; - dump_exception_info.ExceptionPointers = exception_pointers_; - dump_exception_info.ClientPointers = is_client_pointers_; - } - - // Add an MDRawBreakpadInfo stream to the minidump, to provide additional - // information about the exception handler to the Breakpad processor. - // The information will help the processor determine which threads are - // relevant. The Breakpad processor does not require this information but - // can function better with Breakpad-generated dumps when it is present. - // The native debugger is not harmed by the presence of this information. - MDRawBreakpadInfo breakpad_info = {0}; - if (!is_client_pointers_) { - // Set the dump thread id and requesting thread id only in case of - // in-process dump generation. - breakpad_info.validity = MD_BREAKPAD_INFO_VALID_DUMP_THREAD_ID | - MD_BREAKPAD_INFO_VALID_REQUESTING_THREAD_ID; - breakpad_info.dump_thread_id = thread_id_; - breakpad_info.requesting_thread_id = requesting_thread_id_; - } - - int additional_streams_count = additional_streams_ ? - additional_streams_->UserStreamCount : 0; - scoped_array<MINIDUMP_USER_STREAM> user_stream_array( - new MINIDUMP_USER_STREAM[3 + additional_streams_count]); - user_stream_array[0].Type = MD_BREAKPAD_INFO_STREAM; - user_stream_array[0].BufferSize = sizeof(breakpad_info); - user_stream_array[0].Buffer = &breakpad_info; - - MINIDUMP_USER_STREAM_INFORMATION user_streams; - user_streams.UserStreamCount = 1; - user_streams.UserStreamArray = user_stream_array.get(); - - MDRawAssertionInfo* actual_assert_info = assert_info_; - MDRawAssertionInfo client_assert_info = {{0}}; - - if (assert_info_) { - // If the assertion info object lives in the client process, - // read the memory of the client process. - if (is_client_pointers_) { - SIZE_T bytes_read = 0; - if (!ReadProcessMemory(process_handle_, - assert_info_, - &client_assert_info, - sizeof(client_assert_info), - &bytes_read)) { - if (dump_file_is_internal_) - CloseHandle(dump_file_); - if (full_dump_file_is_internal_ && - full_dump_file_ != INVALID_HANDLE_VALUE) - CloseHandle(full_dump_file_); - return false; - } - - if (bytes_read != sizeof(client_assert_info)) { - if (dump_file_is_internal_) - CloseHandle(dump_file_); - if (full_dump_file_is_internal_ && - full_dump_file_ != INVALID_HANDLE_VALUE) - CloseHandle(full_dump_file_); - return false; - } - - actual_assert_info = &client_assert_info; - } - - user_stream_array[1].Type = MD_ASSERTION_INFO_STREAM; - user_stream_array[1].BufferSize = sizeof(MDRawAssertionInfo); - user_stream_array[1].Buffer = actual_assert_info; - ++user_streams.UserStreamCount; - } - - if (additional_streams_) { - for (size_t i = 0; - i < additional_streams_->UserStreamCount; - i++, user_streams.UserStreamCount++) { - user_stream_array[user_streams.UserStreamCount].Type = - additional_streams_->UserStreamArray[i].Type; - user_stream_array[user_streams.UserStreamCount].BufferSize = - additional_streams_->UserStreamArray[i].BufferSize; - user_stream_array[user_streams.UserStreamCount].Buffer = - additional_streams_->UserStreamArray[i].Buffer; - } - } - - // If the process is terminated by STATUS_INVALID_HANDLE exception store - // the trace of operations for the offending handle value. Do nothing special - // if the client already requested the handle trace to be stored in the dump. - HandleTraceData handle_trace_data; - if (exception_pointers_ && (dump_type_ & MiniDumpWithHandleData) == 0) { - if (!handle_trace_data.CollectHandleData(process_handle_, - exception_pointers_)) { - if (dump_file_is_internal_) - CloseHandle(dump_file_); - if (full_dump_file_is_internal_ && - full_dump_file_ != INVALID_HANDLE_VALUE) - CloseHandle(full_dump_file_); - return false; - } - } - - bool result_full_memory = true; - if (full_memory_dump) { - result_full_memory = write_dump( - process_handle_, - process_id_, - full_dump_file_, - static_cast<MINIDUMP_TYPE>((dump_type_ & (~MiniDumpNormal)) - | MiniDumpWithHandleData), - exception_pointers_ ? &dump_exception_info : NULL, - &user_streams, - NULL) != FALSE; - } - - // Add handle operations trace stream to the minidump if it was collected. - if (handle_trace_data.GetUserStream( - &user_stream_array[user_streams.UserStreamCount])) { - ++user_streams.UserStreamCount; - } - - bool result_minidump = write_dump( - process_handle_, - process_id_, - dump_file_, - static_cast<MINIDUMP_TYPE>((dump_type_ & (~MiniDumpWithFullMemory)) - | MiniDumpNormal), - exception_pointers_ ? &dump_exception_info : NULL, - &user_streams, - callback_info_) != FALSE; - - return result_minidump && result_full_memory; -} - -bool MinidumpGenerator::GenerateDumpFile(wstring* dump_path) { - // The dump file was already set by handle or this function was previously - // called. - if (dump_file_ != INVALID_HANDLE_VALUE) { - return false; - } - - wstring dump_file_path; - if (!GenerateDumpFilePath(&dump_file_path)) { - return false; - } - - dump_file_ = CreateFile(dump_file_path.c_str(), - GENERIC_WRITE, - 0, - NULL, - CREATE_NEW, - FILE_ATTRIBUTE_NORMAL, - NULL); - if (dump_file_ == INVALID_HANDLE_VALUE) { - return false; - } - - dump_file_is_internal_ = true; - *dump_path = dump_file_path; - return true; -} - -bool MinidumpGenerator::GenerateFullDumpFile(wstring* full_dump_path) { - // A full minidump was not requested. - if ((dump_type_ & MiniDumpWithFullMemory) == 0) { - return false; - } - - // The dump file was already set by handle or this function was previously - // called. - if (full_dump_file_ != INVALID_HANDLE_VALUE) { - return false; - } - - wstring full_dump_file_path; - if (!GenerateDumpFilePath(&full_dump_file_path)) { - return false; - } - full_dump_file_path.resize(full_dump_file_path.size() - 4); // strip .dmp - full_dump_file_path.append(TEXT("-full.dmp")); - - full_dump_file_ = CreateFile(full_dump_file_path.c_str(), - GENERIC_WRITE, - 0, - NULL, - CREATE_NEW, - FILE_ATTRIBUTE_NORMAL, - NULL); - if (full_dump_file_ == INVALID_HANDLE_VALUE) { - return false; - } - - full_dump_file_is_internal_ = true; - *full_dump_path = full_dump_file_path; - return true; -} - -HMODULE MinidumpGenerator::GetDbghelpModule() { - AutoCriticalSection lock(&module_load_sync_); - if (!dbghelp_module_) { - dbghelp_module_ = LoadLibrary(TEXT("dbghelp.dll")); - } - - return dbghelp_module_; -} - -MinidumpGenerator::MiniDumpWriteDumpType MinidumpGenerator::GetWriteDump() { - AutoCriticalSection lock(&get_proc_address_sync_); - if (!write_dump_) { - HMODULE module = GetDbghelpModule(); - if (module) { - FARPROC proc = GetProcAddress(module, "MiniDumpWriteDump"); - write_dump_ = reinterpret_cast<MiniDumpWriteDumpType>(proc); - } - } - - return write_dump_; -} - -HMODULE MinidumpGenerator::GetRpcrt4Module() { - AutoCriticalSection lock(&module_load_sync_); - if (!rpcrt4_module_) { - rpcrt4_module_ = LoadLibrary(TEXT("rpcrt4.dll")); - } - - return rpcrt4_module_; -} - -MinidumpGenerator::UuidCreateType MinidumpGenerator::GetCreateUuid() { - AutoCriticalSection lock(&module_load_sync_); - if (!create_uuid_) { - HMODULE module = GetRpcrt4Module(); - if (module) { - FARPROC proc = GetProcAddress(module, "UuidCreate"); - create_uuid_ = reinterpret_cast<UuidCreateType>(proc); - } - } - - return create_uuid_; -} - -bool MinidumpGenerator::GenerateDumpFilePath(wstring* file_path) { - UUID id = {0}; - - UuidCreateType create_uuid = GetCreateUuid(); - if (!create_uuid) { - return false; - } - - create_uuid(&id); - wstring id_str = GUIDString::GUIDToWString(&id); - - *file_path = dump_path_ + TEXT("\\") + id_str + TEXT(".dmp"); - return true; -} - -} // namespace google_breakpad diff --git a/toolkit/crashreporter/google-breakpad/src/client/windows/crash_generation/minidump_generator.h b/toolkit/crashreporter/google-breakpad/src/client/windows/crash_generation/minidump_generator.h deleted file mode 100644 index a3c123056..000000000 --- a/toolkit/crashreporter/google-breakpad/src/client/windows/crash_generation/minidump_generator.h +++ /dev/null @@ -1,199 +0,0 @@ -// Copyright (c) 2008, 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. - -#ifndef CLIENT_WINDOWS_CRASH_GENERATION_MINIDUMP_GENERATOR_H_ -#define CLIENT_WINDOWS_CRASH_GENERATION_MINIDUMP_GENERATOR_H_ - -#include <windows.h> -#include <dbghelp.h> -#include <rpc.h> -#include <list> -#include <string> -#include "google_breakpad/common/minidump_format.h" - -namespace google_breakpad { - -// Abstraction for various objects and operations needed to generate -// minidump on Windows. This abstraction is useful to hide all the gory -// details for minidump generation and provide a clean interface to -// the clients to generate minidumps. -class MinidumpGenerator { - public: - // Creates an instance with the given parameters. - // is_client_pointers specifies whether the exception_pointers and - // assert_info point into the process that is being dumped. - // Before calling WriteMinidump on the returned instance a dump file muct be - // specified by a call to either SetDumpFile() or GenerateDumpFile(). - // If a full dump file will be requested via a subsequent call to either - // SetFullDumpFile or GenerateFullDumpFile() dump_type must include - // MiniDumpWithFullMemory. - MinidumpGenerator(const std::wstring& dump_path, - const HANDLE process_handle, - const DWORD process_id, - const DWORD thread_id, - const DWORD requesting_thread_id, - EXCEPTION_POINTERS* exception_pointers, - MDRawAssertionInfo* assert_info, - const MINIDUMP_TYPE dump_type, - const bool is_client_pointers); - - ~MinidumpGenerator(); - - void SetDumpFile(const HANDLE dump_file) { dump_file_ = dump_file; } - void SetFullDumpFile(const HANDLE full_dump_file) { - full_dump_file_ = full_dump_file; - } - - // Generate the name for the dump file that will be written to once - // WriteMinidump() is called. Can only be called once and cannot be called - // if the dump file is set via SetDumpFile(). - bool GenerateDumpFile(std::wstring* dump_path); - - // Generate the name for the full dump file that will be written to once - // WriteMinidump() is called. Cannot be called unless the minidump type - // includes MiniDumpWithFullMemory. Can only be called once and cannot be - // called if the dump file is set via SetFullDumpFile(). - bool GenerateFullDumpFile(std::wstring* full_dump_path); - - void SetAdditionalStreams( - MINIDUMP_USER_STREAM_INFORMATION* additional_streams) { - additional_streams_ = additional_streams; - } - - void SetCallback(MINIDUMP_CALLBACK_INFORMATION* callback_info) { - callback_info_ = callback_info; - } - - // Writes the minidump with the given parameters. Stores the - // dump file path in the dump_path parameter if dump generation - // succeeds. - bool WriteMinidump(); - - private: - // Function pointer type for MiniDumpWriteDump, which is looked up - // dynamically. - typedef BOOL (WINAPI* MiniDumpWriteDumpType)( - HANDLE hProcess, - DWORD ProcessId, - HANDLE hFile, - MINIDUMP_TYPE DumpType, - CONST PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam, - CONST PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam, - CONST PMINIDUMP_CALLBACK_INFORMATION CallbackParam); - - // Function pointer type for UuidCreate, which is looked up dynamically. - typedef RPC_STATUS (RPC_ENTRY* UuidCreateType)(UUID* Uuid); - - // Loads the appropriate DLL lazily in a thread safe way. - HMODULE GetDbghelpModule(); - - // Loads the appropriate DLL and gets a pointer to the MiniDumpWriteDump - // function lazily and in a thread-safe manner. - MiniDumpWriteDumpType GetWriteDump(); - - // Loads the appropriate DLL lazily in a thread safe way. - HMODULE GetRpcrt4Module(); - - // Loads the appropriate DLL and gets a pointer to the UuidCreate - // function lazily and in a thread-safe manner. - UuidCreateType GetCreateUuid(); - - // Returns the path for the file to write dump to. - bool GenerateDumpFilePath(std::wstring* file_path); - - // Handle to dynamically loaded DbgHelp.dll. - HMODULE dbghelp_module_; - - // Pointer to the MiniDumpWriteDump function. - MiniDumpWriteDumpType write_dump_; - - // Handle to dynamically loaded rpcrt4.dll. - HMODULE rpcrt4_module_; - - // Pointer to the UuidCreate function. - UuidCreateType create_uuid_; - - // Handle for the process to dump. - HANDLE process_handle_; - - // Process ID for the process to dump. - DWORD process_id_; - - // The crashing thread ID. - DWORD thread_id_; - - // The thread ID which is requesting the dump. - DWORD requesting_thread_id_; - - // Pointer to the exception information for the crash. This may point to an - // address in the crashing process so it should not be dereferenced. - EXCEPTION_POINTERS* exception_pointers_; - - // Assertion info for the report. - MDRawAssertionInfo* assert_info_; - - // Type of minidump to generate. - MINIDUMP_TYPE dump_type_; - - // Specifies whether the exception_pointers_ reference memory in the crashing - // process. - bool is_client_pointers_; - - // Folder path to store dump files. - std::wstring dump_path_; - - // The file where the dump will be written. - HANDLE dump_file_; - - // The file where the full dump will be written. - HANDLE full_dump_file_; - - // Tracks whether the dump file handle is managed externally. - bool dump_file_is_internal_; - - // Tracks whether the full dump file handle is managed externally. - bool full_dump_file_is_internal_; - - // Additional streams to be written to the dump. - MINIDUMP_USER_STREAM_INFORMATION* additional_streams_; - - // The user defined callback for the various stages of the dump process. - MINIDUMP_CALLBACK_INFORMATION* callback_info_; - - // Critical section to sychronize action of loading modules dynamically. - CRITICAL_SECTION module_load_sync_; - - // Critical section to synchronize action of dynamically getting function - // addresses from modules. - CRITICAL_SECTION get_proc_address_sync_; -}; - -} // namespace google_breakpad - -#endif // CLIENT_WINDOWS_CRASH_GENERATION_MINIDUMP_GENERATOR_H_ diff --git a/toolkit/crashreporter/google-breakpad/src/client/windows/crash_generation/objs.mozbuild b/toolkit/crashreporter/google-breakpad/src/client/windows/crash_generation/objs.mozbuild deleted file mode 100644 index 549c14e10..000000000 --- a/toolkit/crashreporter/google-breakpad/src/client/windows/crash_generation/objs.mozbuild +++ /dev/null @@ -1,17 +0,0 @@ -# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- -# vim: set filetype=python: -# This Source Code Form is subject to the terms of the Mozilla Public -# License, v. 2.0. If a copy of the MPL was not distributed with this -# file, You can obtain one at http://mozilla.org/MPL/2.0/. - -lobjs_crash_generation = [ - 'client_info.cc', - 'crash_generation_client.cc', - 'crash_generation_server.cc', - 'minidump_generator.cc', -] - -subdir = 'toolkit/crashreporter/google-breakpad/src/client/windows/crash_generation' -objs_crash_generation = [ - '/%s/%s' % (subdir, s) for s in lobjs_crash_generation -] |