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:
ted.mielczarek 2012-07-16 15:16:01 +00:00
parent e05aab7b6b
commit 534189b735
4 changed files with 120 additions and 4 deletions

View file

@ -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

View file

@ -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_;

View file

@ -71,6 +71,26 @@ ExceptionHandler::ExceptionHandler(const wstring& dump_path,
handler_types, handler_types,
dump_type, dump_type,
pipe_name, pipe_name,
NULL,
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); custom_info);
} }
@ -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.

View file

@ -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