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
This commit is contained in:
parent
c75e316359
commit
def0b7a7b0
8 changed files with 196 additions and 49 deletions
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
@ -265,6 +279,21 @@ bool Breakpad::ExceptionHandlerDirectCallback(void *context,
|
|||
crashing_thread);
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
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 -
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -710,6 +758,16 @@ bool Breakpad::HandleException(int exception_type,
|
|||
return false;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
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;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//=============================================================================
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
84
src/common/mac/launch_reporter.cc
Normal file
84
src/common/mac/launch_reporter.cc
Normal file
|
@ -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
|
43
src/common/mac/launch_reporter.h
Normal file
43
src/common/mac/launch_reporter.h
Normal file
|
@ -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__
|
Loading…
Reference in a new issue