aboutsummaryrefslogtreecommitdiff
path: root/src/client/windows/crash_generation
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/windows/crash_generation')
-rw-r--r--src/client/windows/crash_generation/crash_generation_client.cc56
-rw-r--r--src/client/windows/crash_generation/crash_generation_client.h16
2 files changed, 72 insertions, 0 deletions
diff --git a/src/client/windows/crash_generation/crash_generation_client.cc b/src/client/windows/crash_generation/crash_generation_client.cc
index ffbcaf20..b0d3d04d 100644
--- a/src/client/windows/crash_generation/crash_generation_client.cc
+++ b/src/client/windows/crash_generation/crash_generation_client.cc
@@ -95,6 +95,27 @@ CrashGenerationClient::CrashGenerationClient(
MINIDUMP_TYPE dump_type,
const CustomClientInfo* custom_info)
: 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),
thread_id_(0),
server_process_id_(0),
@@ -248,6 +269,12 @@ bool CrashGenerationClient::RegisterClient(HANDLE pipe) {
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,
@@ -342,4 +369,33 @@ bool CrashGenerationClient::SignalCrashEventAndWait() {
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/src/client/windows/crash_generation/crash_generation_client.h b/src/client/windows/crash_generation/crash_generation_client.h
index 85a0456c..2ce14dd2 100644
--- a/src/client/windows/crash_generation/crash_generation_client.h
+++ b/src/client/windows/crash_generation/crash_generation_client.h
@@ -66,6 +66,10 @@ class CrashGenerationClient {
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.
@@ -96,6 +100,14 @@ class CrashGenerationClient {
// 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.
//
@@ -127,6 +139,10 @@ class CrashGenerationClient {
// 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_;