Allow the crash generation server to be initialized with a handle instead of a pipe name
A=bsmedberg R=ted at http://breakpad.appspot.com/406002 git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@985 4c0a9323-5329-0410-9bdc-e9ce6186880e
This commit is contained in:
parent
e05aab7b6b
commit
534189b735
4 changed files with 120 additions and 4 deletions
|
@ -95,6 +95,27 @@ CrashGenerationClient::CrashGenerationClient(
|
||||||
MINIDUMP_TYPE dump_type,
|
MINIDUMP_TYPE dump_type,
|
||||||
const CustomClientInfo* custom_info)
|
const CustomClientInfo* custom_info)
|
||||||
: pipe_name_(pipe_name),
|
: pipe_name_(pipe_name),
|
||||||
|
pipe_handle_(NULL),
|
||||||
|
dump_type_(dump_type),
|
||||||
|
thread_id_(0),
|
||||||
|
server_process_id_(0),
|
||||||
|
crash_event_(NULL),
|
||||||
|
crash_generated_(NULL),
|
||||||
|
server_alive_(NULL),
|
||||||
|
exception_pointers_(NULL),
|
||||||
|
custom_info_() {
|
||||||
|
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),
|
||||||
dump_type_(dump_type),
|
dump_type_(dump_type),
|
||||||
thread_id_(0),
|
thread_id_(0),
|
||||||
server_process_id_(0),
|
server_process_id_(0),
|
||||||
|
@ -248,6 +269,12 @@ bool CrashGenerationClient::RegisterClient(HANDLE pipe) {
|
||||||
HANDLE CrashGenerationClient::ConnectToPipe(const wchar_t* pipe_name,
|
HANDLE CrashGenerationClient::ConnectToPipe(const wchar_t* pipe_name,
|
||||||
DWORD pipe_access,
|
DWORD pipe_access,
|
||||||
DWORD flags_attrs) {
|
DWORD flags_attrs) {
|
||||||
|
if (pipe_handle_) {
|
||||||
|
HANDLE t = pipe_handle_;
|
||||||
|
pipe_handle_ = NULL;
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
for (int i = 0; i < kPipeConnectMaxAttempts; ++i) {
|
for (int i = 0; i < kPipeConnectMaxAttempts; ++i) {
|
||||||
HANDLE pipe = CreateFile(pipe_name,
|
HANDLE pipe = CreateFile(pipe_name,
|
||||||
pipe_access,
|
pipe_access,
|
||||||
|
@ -342,4 +369,33 @@ bool CrashGenerationClient::SignalCrashEventAndWait() {
|
||||||
return result == WAIT_OBJECT_0;
|
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
|
} // namespace google_breakpad
|
||||||
|
|
|
@ -66,6 +66,10 @@ class CrashGenerationClient {
|
||||||
MINIDUMP_TYPE dump_type,
|
MINIDUMP_TYPE dump_type,
|
||||||
const CustomClientInfo* custom_info);
|
const CustomClientInfo* custom_info);
|
||||||
|
|
||||||
|
CrashGenerationClient(HANDLE pipe_handle,
|
||||||
|
MINIDUMP_TYPE dump_type,
|
||||||
|
const CustomClientInfo* custom_info);
|
||||||
|
|
||||||
~CrashGenerationClient();
|
~CrashGenerationClient();
|
||||||
|
|
||||||
// Registers the client process with the crash server.
|
// Registers the client process with the crash server.
|
||||||
|
@ -96,6 +100,14 @@ class CrashGenerationClient {
|
||||||
// false will be returned.
|
// false will be returned.
|
||||||
bool RequestDump(MDRawAssertionInfo* assert_info);
|
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:
|
private:
|
||||||
// Connects to the appropriate pipe and sets the pipe handle state.
|
// Connects to the appropriate pipe and sets the pipe handle state.
|
||||||
//
|
//
|
||||||
|
@ -127,6 +139,10 @@ class CrashGenerationClient {
|
||||||
// Pipe name to use to talk to server.
|
// Pipe name to use to talk to server.
|
||||||
std::wstring pipe_name_;
|
std::wstring pipe_name_;
|
||||||
|
|
||||||
|
// Pipe handle duplicated from server process. Only valid before
|
||||||
|
// Register is called.
|
||||||
|
HANDLE pipe_handle_;
|
||||||
|
|
||||||
// Custom client information
|
// Custom client information
|
||||||
CustomClientInfo custom_info_;
|
CustomClientInfo custom_info_;
|
||||||
|
|
||||||
|
|
|
@ -71,9 +71,29 @@ ExceptionHandler::ExceptionHandler(const wstring& dump_path,
|
||||||
handler_types,
|
handler_types,
|
||||||
dump_type,
|
dump_type,
|
||||||
pipe_name,
|
pipe_name,
|
||||||
|
NULL,
|
||||||
custom_info);
|
custom_info);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ExceptionHandler::ExceptionHandler(const wstring& dump_path,
|
||||||
|
FilterCallback filter,
|
||||||
|
MinidumpCallback callback,
|
||||||
|
void* callback_context,
|
||||||
|
int handler_types,
|
||||||
|
MINIDUMP_TYPE dump_type,
|
||||||
|
HANDLE pipe_handle,
|
||||||
|
const CustomClientInfo* custom_info) {
|
||||||
|
Initialize(dump_path,
|
||||||
|
filter,
|
||||||
|
callback,
|
||||||
|
callback_context,
|
||||||
|
handler_types,
|
||||||
|
dump_type,
|
||||||
|
NULL,
|
||||||
|
pipe_handle,
|
||||||
|
custom_info);
|
||||||
|
}
|
||||||
|
|
||||||
ExceptionHandler::ExceptionHandler(const wstring &dump_path,
|
ExceptionHandler::ExceptionHandler(const wstring &dump_path,
|
||||||
FilterCallback filter,
|
FilterCallback filter,
|
||||||
MinidumpCallback callback,
|
MinidumpCallback callback,
|
||||||
|
@ -86,6 +106,7 @@ ExceptionHandler::ExceptionHandler(const wstring &dump_path,
|
||||||
handler_types,
|
handler_types,
|
||||||
MiniDumpNormal,
|
MiniDumpNormal,
|
||||||
NULL,
|
NULL,
|
||||||
|
NULL,
|
||||||
NULL);
|
NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -96,6 +117,7 @@ void ExceptionHandler::Initialize(const wstring& dump_path,
|
||||||
int handler_types,
|
int handler_types,
|
||||||
MINIDUMP_TYPE dump_type,
|
MINIDUMP_TYPE dump_type,
|
||||||
const wchar_t* pipe_name,
|
const wchar_t* pipe_name,
|
||||||
|
HANDLE pipe_handle,
|
||||||
const CustomClientInfo* custom_info) {
|
const CustomClientInfo* custom_info) {
|
||||||
LONG instance_count = InterlockedIncrement(&instance_count_);
|
LONG instance_count = InterlockedIncrement(&instance_count_);
|
||||||
filter_ = filter;
|
filter_ = filter;
|
||||||
|
@ -125,12 +147,22 @@ void ExceptionHandler::Initialize(const wstring& dump_path,
|
||||||
handler_return_value_ = false;
|
handler_return_value_ = false;
|
||||||
handle_debug_exceptions_ = false;
|
handle_debug_exceptions_ = false;
|
||||||
|
|
||||||
// Attempt to use out-of-process if user has specified pipe name.
|
// Attempt to use out-of-process if user has specified a pipe.
|
||||||
if (pipe_name != NULL) {
|
if (pipe_name != NULL || pipe_handle != NULL) {
|
||||||
scoped_ptr<CrashGenerationClient> client(
|
assert(!(pipe_name && pipe_handle));
|
||||||
|
|
||||||
|
scoped_ptr<CrashGenerationClient> client;
|
||||||
|
if (pipe_name) {
|
||||||
|
client.reset(
|
||||||
new CrashGenerationClient(pipe_name,
|
new CrashGenerationClient(pipe_name,
|
||||||
dump_type_,
|
dump_type_,
|
||||||
custom_info));
|
custom_info));
|
||||||
|
} else {
|
||||||
|
client.reset(
|
||||||
|
new CrashGenerationClient(pipe_handle,
|
||||||
|
dump_type_,
|
||||||
|
custom_info));
|
||||||
|
}
|
||||||
|
|
||||||
// If successful in registering with the monitoring process,
|
// If successful in registering with the monitoring process,
|
||||||
// there is no need to setup in-process crash generation.
|
// there is no need to setup in-process crash generation.
|
||||||
|
|
|
@ -153,7 +153,7 @@ class ExceptionHandler {
|
||||||
void* callback_context,
|
void* callback_context,
|
||||||
int handler_types);
|
int handler_types);
|
||||||
|
|
||||||
// Creates a new ExcetpionHandler instance that can attempt to perform
|
// Creates a new ExceptionHandler instance that can attempt to perform
|
||||||
// out-of-process dump generation if pipe_name is not NULL. If pipe_name is
|
// out-of-process dump generation if pipe_name is not NULL. If pipe_name is
|
||||||
// NULL, or if out-of-process dump generation registration step fails,
|
// NULL, or if out-of-process dump generation registration step fails,
|
||||||
// in-process dump generation will be used. This also allows specifying
|
// in-process dump generation will be used. This also allows specifying
|
||||||
|
@ -167,6 +167,17 @@ class ExceptionHandler {
|
||||||
const wchar_t* pipe_name,
|
const wchar_t* pipe_name,
|
||||||
const CustomClientInfo* custom_info);
|
const CustomClientInfo* custom_info);
|
||||||
|
|
||||||
|
// As above, creates a new ExceptionHandler instance to perform
|
||||||
|
// out-of-process dump generation if the given pipe_handle is not NULL.
|
||||||
|
ExceptionHandler(const wstring& dump_path,
|
||||||
|
FilterCallback filter,
|
||||||
|
MinidumpCallback callback,
|
||||||
|
void* callback_context,
|
||||||
|
int handler_types,
|
||||||
|
MINIDUMP_TYPE dump_type,
|
||||||
|
HANDLE pipe_handle,
|
||||||
|
const CustomClientInfo* custom_info);
|
||||||
|
|
||||||
~ExceptionHandler();
|
~ExceptionHandler();
|
||||||
|
|
||||||
// Get and set the minidump path.
|
// Get and set the minidump path.
|
||||||
|
@ -219,6 +230,7 @@ class ExceptionHandler {
|
||||||
int handler_types,
|
int handler_types,
|
||||||
MINIDUMP_TYPE dump_type,
|
MINIDUMP_TYPE dump_type,
|
||||||
const wchar_t* pipe_name,
|
const wchar_t* pipe_name,
|
||||||
|
HANDLE pipe_handle,
|
||||||
const CustomClientInfo* custom_info);
|
const CustomClientInfo* custom_info);
|
||||||
|
|
||||||
// Function pointer type for MiniDumpWriteDump, which is looked up
|
// Function pointer type for MiniDumpWriteDump, which is looked up
|
||||||
|
|
Loading…
Reference in a new issue