1
0
mirror of https://github.com/tomahawk-player/tomahawk.git synced 2025-08-29 00:30:04 +02:00

* Updated breakpad to latest version.

This commit is contained in:
Christian Muehlhaeuser
2012-06-24 18:25:34 +02:00
parent ffd2cee2ff
commit 6aae2dd96f
186 changed files with 9184 additions and 5835 deletions

View File

@@ -31,6 +31,7 @@
#include "client/windows/common/ipc_protocol.h"
static const wchar_t kCustomInfoProcessUptimeName[] = L"ptime";
static const size_t kMaxCustomInfoEntries = 4096;
namespace google_breakpad {
@@ -52,7 +53,8 @@ ClientInfo::ClientInfo(CrashGenerationServer* crash_server,
dump_requested_handle_(NULL),
dump_generated_handle_(NULL),
dump_request_wait_handle_(NULL),
process_exit_wait_handle_(NULL) {
process_exit_wait_handle_(NULL),
crash_id_(NULL) {
GetSystemTimeAsFileTime(&start_time_);
}
@@ -62,6 +64,12 @@ bool ClientInfo::Initialize() {
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))
crash_id_ = creation_time.dwLowDateTime;
dump_requested_handle_ = CreateEvent(NULL, // Security attributes.
TRUE, // Manual reset.
FALSE, // Initial state.
@@ -160,6 +168,9 @@ void ClientInfo::SetProcessUptime() {
}
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;

View File

@@ -65,6 +65,7 @@ class ClientInfo {
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_; }
HANDLE dump_request_wait_handle() const {
return dump_request_wait_handle_;
@@ -160,6 +161,11 @@ class ClientInfo {
// 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);

View File

View File

@@ -167,6 +167,23 @@ bool CrashGenerationClient::Register() {
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,
@@ -223,7 +240,7 @@ bool CrashGenerationClient::RegisterClient(HANDLE pipe) {
crash_event_ = reply.dump_request_handle;
crash_generated_ = reply.dump_generated_handle;
server_alive_ = reply.server_alive_handle;
server_process_id_ = reply.pid;
server_process_id_ = reply.id;
return true;
}
@@ -261,7 +278,7 @@ HANDLE CrashGenerationClient::ConnectToPipe(const wchar_t* pipe_name,
bool CrashGenerationClient::ValidateResponse(
const ProtocolMessage& msg) const {
return (msg.tag == MESSAGE_TAG_REGISTRATION_RESPONSE) &&
(msg.pid != 0) &&
(msg.id != 0) &&
(msg.dump_request_handle != NULL) &&
(msg.dump_generated_handle != NULL) &&
(msg.server_alive_handle != NULL);

View File

@@ -73,6 +73,10 @@ class CrashGenerationClient {
// 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);

View File

@@ -84,11 +84,12 @@ static const int kShutdownDelayMs = 10000;
static const int kShutdownSleepIntervalMs = 5;
static bool IsClientRequestValid(const ProtocolMessage& msg) {
return msg.tag == MESSAGE_TAG_REGISTRATION_REQUEST &&
msg.pid != 0 &&
msg.thread_id != NULL &&
msg.exception_pointers != NULL &&
msg.assert_info != NULL;
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);
}
CrashGenerationServer::CrashGenerationServer(
@@ -100,6 +101,8 @@ CrashGenerationServer::CrashGenerationServer(
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),
@@ -113,6 +116,8 @@ CrashGenerationServer::CrashGenerationServer(
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),
dump_generator_(NULL),
server_state_(IPC_SERVER_STATE_UNINITIALIZED),
@@ -120,7 +125,7 @@ CrashGenerationServer::CrashGenerationServer(
overlapped_(),
client_info_(NULL),
cleanup_item_count_(0) {
InitializeCriticalSection(&clients_sync_);
InitializeCriticalSection(&sync_);
if (dump_path) {
dump_generator_.reset(new MinidumpGenerator(*dump_path));
@@ -128,38 +133,41 @@ CrashGenerationServer::CrashGenerationServer(
}
CrashGenerationServer::~CrashGenerationServer() {
// Indicate to existing threads that server is shutting down.
shutting_down_ = true;
// 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.
// New scope to hold the lock for the shortest time.
// New scope to release the lock automatically.
{
AutoCriticalSection lock(&clients_sync_);
AutoCriticalSection lock(&sync_);
// Indicate to existing threads that server is shutting down.
shutting_down_ = true;
// 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) {
lock.Release();
Sleep(10);
lock.Acquire();
}
// 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.
std::list<ClientInfo*>::iterator iter;
for (iter = clients_.begin(); iter != clients_.end(); ++iter) {
ClientInfo* client_info = *iter;
@@ -180,33 +188,35 @@ CrashGenerationServer::~CrashGenerationServer() {
}
}
// Clean up all the ClientInfo objects.
// New scope to hold the lock for the shortest time.
{
AutoCriticalSection lock(&clients_sync_);
AutoCriticalSection lock(&sync_);
// Clean up all the ClientInfo objects.
std::list<ClientInfo*>::iterator iter;
for (iter = clients_.begin(); iter != clients_.end(); ++iter) {
ClientInfo* client_info = *iter;
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);
}
}
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(&clients_sync_);
DeleteCriticalSection(&sync_);
}
bool CrashGenerationServer::Start() {
AutoCriticalSection lock(&sync_);
if (server_state_ != IPC_SERVER_STATE_UNINITIALIZED) {
return false;
}
@@ -416,9 +426,16 @@ void CrashGenerationServer::HandleReadDoneState() {
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_.pid,
msg_.id,
msg_.dump_type,
msg_.thread_id,
msg_.exception_pointers,
@@ -582,7 +599,7 @@ void CrashGenerationServer::EnterStateImmediately(IPCServerState state) {
bool CrashGenerationServer::PrepareReply(const ClientInfo& client_info,
ProtocolMessage* reply) const {
reply->tag = MESSAGE_TAG_REGISTRATION_RESPONSE;
reply->pid = GetCurrentProcessId();
reply->id = GetCurrentProcessId();
if (CreateClientHandles(client_info, reply)) {
return true;
@@ -670,6 +687,8 @@ bool CrashGenerationServer::RespondToClient(ClientInfo* client_info) {
// implements the state machine described in ReadMe.txt along with the
// helper methods HandleXXXState.
void CrashGenerationServer::HandleConnectionRequest() {
AutoCriticalSection lock(&sync_);
// If we are shutting doen then get into ERROR state, reset the event so more
// workers don't run and return immediately.
if (shutting_down_) {
@@ -756,7 +775,7 @@ bool CrashGenerationServer::AddClient(ClientInfo* client_info) {
// New scope to hold the lock for the shortest time.
{
AutoCriticalSection lock(&clients_sync_);
AutoCriticalSection lock(&sync_);
clients_.push_back(client_info);
}
@@ -793,6 +812,7 @@ void CALLBACK CrashGenerationServer::OnClientEnd(void* context, BOOLEAN) {
CrashGenerationServer* crash_server = client_info->crash_server();
assert(crash_server);
client_info->UnregisterWaits();
InterlockedIncrement(&crash_server->cleanup_item_count_);
if (!QueueUserWorkItem(CleanupClient, context, WT_EXECUTEDEFAULT)) {
@@ -823,7 +843,7 @@ void CrashGenerationServer::DoCleanup(ClientInfo* client_info) {
// Start a new scope to release lock automatically.
{
AutoCriticalSection lock(&clients_sync_);
AutoCriticalSection lock(&sync_);
clients_.remove(client_info);
}

View File

@@ -59,6 +59,9 @@ class CrashGenerationServer {
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
@@ -86,6 +89,8 @@ class CrashGenerationServer {
void* dump_context,
OnClientExitedCallback exit_callback,
void* exit_context,
OnClientUploadRequestCallback upload_request_callback,
void* upload_context,
bool generate_dumps,
const std::wstring* dump_path);
@@ -211,8 +216,9 @@ class CrashGenerationServer {
// asynchronous IO operation.
void EnterStateWhenSignaled(IPCServerState state);
// Sync object for thread-safe access to the shared list of clients.
CRITICAL_SECTION clients_sync_;
// Sync object for thread-safe access to the shared list of clients and
// the server's state.
CRITICAL_SECTION sync_;
// List of clients.
std::list<ClientInfo*> clients_;
@@ -250,6 +256,12 @@ class CrashGenerationServer {
// 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_;
@@ -260,10 +272,10 @@ class CrashGenerationServer {
// 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.
volatile IPCServerState server_state_;
IPCServerState server_state_;
// Whether the server is shutting down.
volatile bool shutting_down_;
bool shutting_down_;
// Overlapped instance for async I/O on the pipe.
OVERLAPPED overlapped_;