aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorandresantoso@chromium.org <andresantoso@chromium.org>2014-09-15 22:48:18 +0000
committerandresantoso@chromium.org <andresantoso@chromium.org>2014-09-15 22:48:18 +0000
commitdef0b7a7b0c4ad3c2f27ddddffcbba7892594da6 (patch)
treeb7af14b1b86942c590c0ae074eda01e72a404e4c /src
parentThis CL initialize NSData in HTTPMultipartUpload.m to nil. (diff)
downloadbreakpad-def0b7a7b0c4ad3c2f27ddddffcbba7892594da6.tar.xz
Mac: Add support for in-process crash reporting to Breakpad.
Add new option BREAKPAD_IN_PROCESS. If YES, Breakpad will write the dump file in-process and then launch the reporter executable as a child process. Originally reviewed at https://codereview.chromium.org/571523004/ BUG=chromium:414239 R=mark@chromium.org Review URL: https://breakpad.appspot.com/1714002 git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1375 4c0a9323-5329-0410-9bdc-e9ce6186880e
Diffstat (limited to 'src')
-rw-r--r--src/client/apple/Framework/BreakpadDefines.h1
-rw-r--r--src/client/mac/Framework/Breakpad.h5
-rw-r--r--src/client/mac/Framework/Breakpad.mm58
-rw-r--r--src/client/mac/crash_generation/ConfigFile.mm2
-rw-r--r--src/client/mac/crash_generation/Inspector.h1
-rw-r--r--src/client/mac/crash_generation/Inspector.mm51
-rw-r--r--src/common/mac/launch_reporter.cc84
-rw-r--r--src/common/mac/launch_reporter.h43
8 files changed, 196 insertions, 49 deletions
diff --git a/src/client/apple/Framework/BreakpadDefines.h b/src/client/apple/Framework/BreakpadDefines.h
index 8986cd1b..410a5a6f 100644
--- a/src/client/apple/Framework/BreakpadDefines.h
+++ b/src/client/apple/Framework/BreakpadDefines.h
@@ -62,6 +62,7 @@
#define BREAKPAD_EMAIL "BreakpadEmail"
#define BREAKPAD_SERVER_TYPE "BreakpadServerType"
#define BREAKPAD_SERVER_PARAMETER_DICT "BreakpadServerParameters"
+#define BREAKPAD_IN_PROCESS "BreakpadInProcess"
// The keys below are NOT user supplied, and are used internally.
#define BREAKPAD_PROCESS_START_TIME "BreakpadProcStartTime"
diff --git a/src/client/mac/Framework/Breakpad.h b/src/client/mac/Framework/Breakpad.h
index dbc620eb..dc7e45d1 100644
--- a/src/client/mac/Framework/Breakpad.h
+++ b/src/client/mac/Framework/Breakpad.h
@@ -158,6 +158,11 @@ typedef bool (*BreakpadFilterCallback)(int exception_type,
// but pass as URL parameters when
// uploading theminidump to the crash
// server.
+//
+// BREAKPAD_IN_PROCESS A boolean NSNumber value. If YES, Breakpad
+// will write the dump file in-process and then
+// launch the reporter executable as a child
+// process.
//=============================================================================
// The BREAKPAD_PRODUCT, BREAKPAD_VERSION and BREAKPAD_URL are
// required to have non-NULL values. By default, the BREAKPAD_PRODUCT
diff --git a/src/client/mac/Framework/Breakpad.mm b/src/client/mac/Framework/Breakpad.mm
index fe592bf3..3b4b6674 100644
--- a/src/client/mac/Framework/Breakpad.mm
+++ b/src/client/mac/Framework/Breakpad.mm
@@ -44,6 +44,7 @@
#import "client/mac/Framework/Breakpad.h"
#import "client/mac/Framework/OnDemandServer.h"
#import "client/mac/handler/protected_memory_allocator.h"
+#include "common/mac/launch_reporter.h"
#import "common/mac/MachIPC.h"
#import "common/simple_string_dictionary.h"
@@ -173,6 +174,8 @@ class Breakpad {
}
bool Initialize(NSDictionary *parameters);
+ bool InitializeInProcess(NSDictionary *parameters);
+ bool InitializeOutOfProcess(NSDictionary *parameters);
bool ExtractParameters(NSDictionary *parameters);
@@ -188,6 +191,17 @@ class Breakpad {
int exception_subcode,
mach_port_t crashing_thread);
+ // Dispatches to HandleMinidump().
+ // This gets called instead of ExceptionHandlerDirectCallback when running
+ // with the BREAKPAD_IN_PROCESS option.
+ static bool HandleMinidumpCallback(const char *dump_dir,
+ const char *minidump_id,
+ void *context,
+ bool succeeded);
+
+ // This is only used when BREAKPAD_IN_PROCESS is YES.
+ bool HandleMinidump(const char *dump_dir, const char *minidump_id);
+
// Since ExceptionHandler (w/o namespace) is defined as typedef in OSX's
// MachineExceptions.h, we have to explicitly name the handler.
google_breakpad::ExceptionHandler *handler_; // The actual handler (STRONG)
@@ -266,6 +280,21 @@ bool Breakpad::ExceptionHandlerDirectCallback(void *context,
}
//=============================================================================
+bool Breakpad::HandleMinidumpCallback(const char *dump_dir,
+ const char *minidump_id,
+ void *context,
+ bool succeeded) {
+ Breakpad *breakpad = (Breakpad *)context;
+
+ // If our context is damaged or something, just return false to indicate that
+ // the handler should continue without us.
+ if (!breakpad || !succeeded)
+ return false;
+
+ return breakpad->HandleMinidump(dump_dir, minidump_id);
+}
+
+//=============================================================================
#pragma mark -
#include <dlfcn.h>
@@ -326,6 +355,25 @@ bool Breakpad::Initialize(NSDictionary *parameters) {
return false;
}
+ if ([[parameters objectForKey:@BREAKPAD_IN_PROCESS] boolValue])
+ return InitializeInProcess(parameters);
+ else
+ return InitializeOutOfProcess(parameters);
+}
+
+//=============================================================================
+bool Breakpad::InitializeInProcess(NSDictionary* parameters) {
+ handler_ =
+ new (gBreakpadAllocator->Allocate(
+ sizeof(google_breakpad::ExceptionHandler)))
+ google_breakpad::ExceptionHandler(
+ config_params_->GetValueForKey(BREAKPAD_DUMP_DIRECTORY),
+ 0, &HandleMinidumpCallback, this, true, 0);
+ return true;
+}
+
+//=============================================================================
+bool Breakpad::InitializeOutOfProcess(NSDictionary* parameters) {
// Get path to Inspector executable.
NSString *inspectorPathString = KeyValue(@BREAKPAD_INSPECTOR_LOCATION);
@@ -711,6 +759,16 @@ bool Breakpad::HandleException(int exception_type,
}
//=============================================================================
+bool Breakpad::HandleMinidump(const char *dump_dir, const char *minidump_id) {
+ google_breakpad::ConfigFile config_file;
+ config_file.WriteFile(dump_dir, config_params_, dump_dir, minidump_id);
+ google_breakpad::LaunchReporter(
+ config_params_->GetValueForKey(BREAKPAD_REPORTER_EXE_LOCATION),
+ config_file.GetFilePath());
+ return true;
+}
+
+//=============================================================================
//=============================================================================
#pragma mark -
diff --git a/src/client/mac/crash_generation/ConfigFile.mm b/src/client/mac/crash_generation/ConfigFile.mm
index dbb0f24d..acab7de8 100644
--- a/src/client/mac/crash_generation/ConfigFile.mm
+++ b/src/client/mac/crash_generation/ConfigFile.mm
@@ -36,7 +36,7 @@
#include <sys/time.h>
#import "client/apple/Framework/BreakpadDefines.h"
-#import "GTMDefines.h"
+#import "common/mac/GTMDefines.h"
namespace google_breakpad {
diff --git a/src/client/mac/crash_generation/Inspector.h b/src/client/mac/crash_generation/Inspector.h
index 7e2eec80..67123551 100644
--- a/src/client/mac/crash_generation/Inspector.h
+++ b/src/client/mac/crash_generation/Inspector.h
@@ -138,7 +138,6 @@ class Inspector {
bool InspectTask();
kern_return_t SendAcknowledgement();
- void LaunchReporter(const char *inConfigFilePath);
// The bootstrap port in which the inspector is registered and into which it
// must check in.
diff --git a/src/client/mac/crash_generation/Inspector.mm b/src/client/mac/crash_generation/Inspector.mm
index d226ca38..dc6f4808 100644
--- a/src/client/mac/crash_generation/Inspector.mm
+++ b/src/client/mac/crash_generation/Inspector.mm
@@ -43,6 +43,7 @@
#import "common/mac/MachIPC.h"
#include "common/mac/bootstrap_compat.h"
+#include "common/mac/launch_reporter.h"
#import "GTMDefines.h"
@@ -76,7 +77,9 @@ void Inspector::Inspect(const char *receive_port_name) {
if (wrote_minidump) {
// Ask the user if he wants to upload the crash report to a server,
// and do so if he agrees.
- LaunchReporter(config_file_.GetFilePath());
+ LaunchReporter(
+ config_params_.GetValueForKey(BREAKPAD_REPORTER_EXE_LOCATION),
+ config_file_.GetFilePath());
} else {
fprintf(stderr, "Inspection of crashed process failed\n");
}
@@ -355,51 +358,5 @@ kern_return_t Inspector::SendAcknowledgement() {
return KERN_INVALID_NAME;
}
-//=============================================================================
-void Inspector::LaunchReporter(const char *inConfigFilePath) {
- // Extract the path to the reporter executable.
- const char *reporterExecutablePath =
- config_params_.GetValueForKey(BREAKPAD_REPORTER_EXE_LOCATION);
-
- // Setup and launch the crash dump sender.
- const char *argv[3];
- argv[0] = reporterExecutablePath;
- argv[1] = inConfigFilePath;
- argv[2] = NULL;
-
- // Launch the reporter
- pid_t pid = fork();
-
- // If we're in the child, load in our new executable and run.
- // The parent will not wait for the child to complete.
- if (pid == 0) {
- execv(argv[0], (char * const *)argv);
- config_file_.Unlink(); // launch failed - get rid of config file
- _exit(1);
- }
-
- // Wait until the Reporter child process exits.
- //
-
- // We'll use a timeout of one minute.
- int timeoutCount = 60; // 60 seconds
-
- while (timeoutCount-- > 0) {
- int status;
- pid_t result = waitpid(pid, &status, WNOHANG);
-
- if (result == 0) {
- // The child has not yet finished.
- sleep(1);
- } else if (result == -1) {
- // error occurred.
- break;
- } else {
- // child has finished
- break;
- }
- }
-}
-
} // namespace google_breakpad
diff --git a/src/common/mac/launch_reporter.cc b/src/common/mac/launch_reporter.cc
new file mode 100644
index 00000000..245be826
--- /dev/null
+++ b/src/common/mac/launch_reporter.cc
@@ -0,0 +1,84 @@
+// Copyright (c) 2014, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <stdio.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+namespace google_breakpad {
+
+void LaunchReporter(const char *reporter_executable_path,
+ const char *config_file_path) {
+ const char* argv[] = { reporter_executable_path, config_file_path, NULL };
+
+ // Launch the reporter
+ pid_t pid = fork();
+
+ if (pid == -1) {
+ perror("fork");
+ fprintf(stderr, "Failed to fork reporter process\n");
+ return;
+ }
+
+ // If we're in the child, load in our new executable and run.
+ // The parent will not wait for the child to complete.
+ if (pid == 0) {
+ execv(argv[0], (char* const*)argv);
+ perror("exec");
+ fprintf(stderr,
+ "Failed to launch reporter process from path %s\n",
+ reporter_executable_path);
+ unlink(config_file_path); // launch failed - get rid of config file
+ _exit(1);
+ }
+
+ // Wait until the Reporter child process exits.
+ //
+
+ // We'll use a timeout of one minute.
+ int timeout_count = 60; // 60 seconds
+
+ while (timeout_count-- > 0) {
+ int status;
+ pid_t result = waitpid(pid, &status, WNOHANG);
+
+ if (result == 0) {
+ // The child has not yet finished.
+ sleep(1);
+ } else if (result == -1) {
+ // error occurred.
+ break;
+ } else {
+ // child has finished
+ break;
+ }
+ }
+}
+
+} // namespace google_breakpad
diff --git a/src/common/mac/launch_reporter.h b/src/common/mac/launch_reporter.h
new file mode 100644
index 00000000..4531123c
--- /dev/null
+++ b/src/common/mac/launch_reporter.h
@@ -0,0 +1,43 @@
+// Copyright (c) 2014, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef COMMON_MAC_LAUNCH_REPORTER_H__
+#define COMMON_MAC_LAUNCH_REPORTER_H__
+
+namespace google_breakpad {
+
+// Launch the crash dump sender app.
+// |reporter_executable_path| is the path to the sender executable.
+// |config_file_path| is the path to the config file.
+void LaunchReporter(const char *reporter_executable_path,
+ const char *config_file_path);
+
+} // namespace google_breakpad
+
+#endif // COMMON_MAC_LAUNCH_REPORTER_H__