Client process uptime is a very useful metric for crashes. Instead of each client process having to keep track of uptime and report it whenever a crash happens, integrate this feature into breakpad OOP code so that all clients get it for free.
I tested this using the test app I have to test OOP stuff. git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@280 4c0a9323-5329-0410-9bdc-e9ce6186880e
This commit is contained in:
parent
38bc56cfa8
commit
3a516e4177
2 changed files with 42 additions and 3 deletions
|
@ -30,6 +30,8 @@
|
||||||
#include "client/windows/crash_generation/client_info.h"
|
#include "client/windows/crash_generation/client_info.h"
|
||||||
#include "client/windows/common/ipc_protocol.h"
|
#include "client/windows/common/ipc_protocol.h"
|
||||||
|
|
||||||
|
static const wchar_t kCustomInfoProcessUptimeName[] = L"ptime";
|
||||||
|
|
||||||
namespace google_breakpad {
|
namespace google_breakpad {
|
||||||
|
|
||||||
ClientInfo::ClientInfo(CrashGenerationServer* crash_server,
|
ClientInfo::ClientInfo(CrashGenerationServer* crash_server,
|
||||||
|
@ -51,6 +53,7 @@ ClientInfo::ClientInfo(CrashGenerationServer* crash_server,
|
||||||
dump_generated_handle_(NULL),
|
dump_generated_handle_(NULL),
|
||||||
dump_request_wait_handle_(NULL),
|
dump_request_wait_handle_(NULL),
|
||||||
process_exit_wait_handle_(NULL) {
|
process_exit_wait_handle_(NULL) {
|
||||||
|
GetSystemTimeAsFileTime(&start_time_);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ClientInfo::Initialize() {
|
bool ClientInfo::Initialize() {
|
||||||
|
@ -146,6 +149,26 @@ bool ClientInfo::GetClientThreadId(DWORD* thread_id) const {
|
||||||
return bytes_count == sizeof(*thread_id);
|
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() {
|
bool ClientInfo::PopulateCustomInfo() {
|
||||||
SIZE_T bytes_count = 0;
|
SIZE_T bytes_count = 0;
|
||||||
SIZE_T read_count = sizeof(CustomInfoEntry) * custom_client_info_.count;
|
SIZE_T read_count = sizeof(CustomInfoEntry) * custom_client_info_.count;
|
||||||
|
@ -155,7 +178,12 @@ bool ClientInfo::PopulateCustomInfo() {
|
||||||
// entries is always the same. So allocate memory only if scoped array has
|
// entries is always the same. So allocate memory only if scoped array has
|
||||||
// a NULL pointer.
|
// a NULL pointer.
|
||||||
if (!custom_info_entries_.get()) {
|
if (!custom_info_entries_.get()) {
|
||||||
custom_info_entries_.reset(new CustomInfoEntry[custom_client_info_.count]);
|
// 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_,
|
if (!ReadProcessMemory(process_handle_,
|
||||||
|
@ -166,13 +194,16 @@ bool ClientInfo::PopulateCustomInfo() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return bytes_count == read_count;
|
SetProcessUptime();
|
||||||
|
return (bytes_count != read_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
CustomClientInfo ClientInfo::GetCustomInfo() const {
|
CustomClientInfo ClientInfo::GetCustomInfo() const {
|
||||||
CustomClientInfo custom_info;
|
CustomClientInfo custom_info;
|
||||||
custom_info.entries = custom_info_entries_.get();
|
custom_info.entries = custom_info_entries_.get();
|
||||||
custom_info.count = custom_client_info_.count;
|
// 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;
|
return custom_info;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -96,6 +96,10 @@ class ClientInfo {
|
||||||
CustomClientInfo GetCustomInfo() const;
|
CustomClientInfo GetCustomInfo() const;
|
||||||
|
|
||||||
private:
|
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.
|
// Crash generation server.
|
||||||
CrashGenerationServer* crash_server_;
|
CrashGenerationServer* crash_server_;
|
||||||
|
|
||||||
|
@ -152,6 +156,10 @@ class ClientInfo {
|
||||||
// Wait handle for process exit event.
|
// Wait handle for process exit event.
|
||||||
HANDLE process_exit_wait_handle_;
|
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_;
|
||||||
|
|
||||||
// Disallow copy ctor and operator=.
|
// Disallow copy ctor and operator=.
|
||||||
ClientInfo(const ClientInfo& client_info);
|
ClientInfo(const ClientInfo& client_info);
|
||||||
ClientInfo& operator=(const ClientInfo& client_info);
|
ClientInfo& operator=(const ClientInfo& client_info);
|
||||||
|
|
Loading…
Reference in a new issue