bug 559228 - Implement multi-process crash reporting on Mac. r=bsmedberg a=blocking
This commit is contained in:
@@ -54,13 +54,13 @@
|
|||||||
int
|
int
|
||||||
main(int argc, char* argv[])
|
main(int argc, char* argv[])
|
||||||
{
|
{
|
||||||
#if defined(MOZ_CRASHREPORTER) && !defined(XP_MACOSX)
|
#if defined(MOZ_CRASHREPORTER)
|
||||||
if (argc < 2)
|
if (argc < 2)
|
||||||
return 1;
|
return 1;
|
||||||
const char* const crashReporterArg = argv[--argc];
|
const char* const crashReporterArg = argv[--argc];
|
||||||
|
|
||||||
# if defined(XP_WIN)
|
# if defined(XP_WIN) || defined(XP_MACOSX)
|
||||||
// on windows, |crashReporterArg| is the named pipe on which the
|
// on windows and mac, |crashReporterArg| is the named pipe on which the
|
||||||
// server is listening for requests, or "-" if crash reporting is
|
// server is listening for requests, or "-" if crash reporting is
|
||||||
// disabled.
|
// disabled.
|
||||||
if (0 != strcmp("-", crashReporterArg)
|
if (0 != strcmp("-", crashReporterArg)
|
||||||
|
|||||||
@@ -318,9 +318,7 @@ GeckoChildProcessHost::PerformAsyncLaunch(std::vector<std::string> aExtraOpts)
|
|||||||
childArgv.push_back("false");
|
childArgv.push_back("false");
|
||||||
}
|
}
|
||||||
# elif defined(XP_MACOSX)
|
# elif defined(XP_MACOSX)
|
||||||
// Call the stub for initialization side effects. Eventually this
|
childArgv.push_back(CrashReporter::GetChildNotificationPipe());
|
||||||
// code will be unified with that above.
|
|
||||||
CrashReporter::CreateNotificationPipeForChild();
|
|
||||||
# endif // OS_LINUX
|
# endif // OS_LINUX
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -52,6 +52,10 @@
|
|||||||
#include <DbgHelp.h>
|
#include <DbgHelp.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#elif defined(XP_MACOSX)
|
#elif defined(XP_MACOSX)
|
||||||
|
#if defined(MOZ_IPC)
|
||||||
|
# include "client/mac/crash_generation/client_info.h"
|
||||||
|
# include "client/mac/crash_generation/crash_generation_server.h"
|
||||||
|
#endif
|
||||||
#include "client/mac/handler/exception_handler.h"
|
#include "client/mac/handler/exception_handler.h"
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <Carbon/Carbon.h>
|
#include <Carbon/Carbon.h>
|
||||||
@@ -104,11 +108,8 @@ CFStringRef reporterClientAppID = CFSTR("org.mozilla.crashreporter");
|
|||||||
#if defined(MOZ_IPC)
|
#if defined(MOZ_IPC)
|
||||||
#include "nsIUUIDGenerator.h"
|
#include "nsIUUIDGenerator.h"
|
||||||
|
|
||||||
#if !defined(XP_MACOSX)
|
|
||||||
using google_breakpad::CrashGenerationServer;
|
using google_breakpad::CrashGenerationServer;
|
||||||
using google_breakpad::ClientInfo;
|
using google_breakpad::ClientInfo;
|
||||||
#endif
|
|
||||||
|
|
||||||
using mozilla::Mutex;
|
using mozilla::Mutex;
|
||||||
using mozilla::MutexAutoLock;
|
using mozilla::MutexAutoLock;
|
||||||
#endif // MOZ_IPC
|
#endif // MOZ_IPC
|
||||||
@@ -191,12 +192,10 @@ static nsCString* crashReporterAPIData = nsnull;
|
|||||||
static nsCString* notesField = nsnull;
|
static nsCString* notesField = nsnull;
|
||||||
|
|
||||||
#if defined(MOZ_IPC)
|
#if defined(MOZ_IPC)
|
||||||
#if !defined(XP_MACOSX)
|
|
||||||
// OOP crash reporting
|
// OOP crash reporting
|
||||||
static CrashGenerationServer* crashServer; // chrome process has this
|
static CrashGenerationServer* crashServer; // chrome process has this
|
||||||
#endif
|
|
||||||
|
|
||||||
# if defined(XP_WIN)
|
# if defined(XP_WIN) || defined(XP_MACOSX)
|
||||||
// If crash reporting is disabled, we hand out this "null" pipe to the
|
// If crash reporting is disabled, we hand out this "null" pipe to the
|
||||||
// child process and don't attempt to connect to a parent server.
|
// child process and don't attempt to connect to a parent server.
|
||||||
static const char kNullNotifyPipe[] = "-";
|
static const char kNullNotifyPipe[] = "-";
|
||||||
@@ -206,6 +205,7 @@ static char* childCrashNotifyPipe;
|
|||||||
static int serverSocketFd = -1;
|
static int serverSocketFd = -1;
|
||||||
static int clientSocketFd = -1;
|
static int clientSocketFd = -1;
|
||||||
static const int kMagicChildCrashReportFd = 42;
|
static const int kMagicChildCrashReportFd = 42;
|
||||||
|
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
// |dumpMapLock| must protect all access to |pidToMinidump|.
|
// |dumpMapLock| must protect all access to |pidToMinidump|.
|
||||||
@@ -571,11 +571,11 @@ nsresult SetExceptionHandler(nsILocalFile* aXREDirectory,
|
|||||||
google_breakpad::ExceptionHandler::HANDLER_ALL);
|
google_breakpad::ExceptionHandler::HANDLER_ALL);
|
||||||
#else
|
#else
|
||||||
true
|
true
|
||||||
#endif
|
|
||||||
#if defined(XP_MACOSX)
|
#if defined(XP_MACOSX)
|
||||||
, NULL
|
, NULL
|
||||||
#endif
|
#endif
|
||||||
);
|
);
|
||||||
|
#endif // XP_WIN32
|
||||||
|
|
||||||
if (!gExceptionHandler)
|
if (!gExceptionHandler)
|
||||||
return NS_ERROR_OUT_OF_MEMORY;
|
return NS_ERROR_OUT_OF_MEMORY;
|
||||||
@@ -604,11 +604,7 @@ nsresult SetExceptionHandler(nsILocalFile* aXREDirectory,
|
|||||||
|
|
||||||
bool GetEnabled()
|
bool GetEnabled()
|
||||||
{
|
{
|
||||||
#if defined(XP_MACOSX)
|
|
||||||
return gExceptionHandler != nsnull;
|
|
||||||
#else
|
|
||||||
return gExceptionHandler != nsnull && !gExceptionHandler->IsOutOfProcess();
|
return gExceptionHandler != nsnull && !gExceptionHandler->IsOutOfProcess();
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GetMinidumpPath(nsAString& aPath)
|
bool GetMinidumpPath(nsAString& aPath)
|
||||||
@@ -1469,16 +1465,27 @@ MoveToPending(nsIFile* dumpFile, nsIFile* extraFile)
|
|||||||
NS_SUCCEEDED(extraFile->MoveTo(pendingDir, EmptyString()));
|
NS_SUCCEEDED(extraFile->MoveTo(pendingDir, EmptyString()));
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !defined(XP_MACOSX)
|
|
||||||
static void
|
static void
|
||||||
OnChildProcessDumpRequested(void* aContext,
|
OnChildProcessDumpRequested(void* aContext,
|
||||||
|
#ifdef XP_MACOSX
|
||||||
|
const ClientInfo& aClientInfo,
|
||||||
|
const xpstring& aFilePath
|
||||||
|
#else
|
||||||
const ClientInfo* aClientInfo,
|
const ClientInfo* aClientInfo,
|
||||||
const xpstring* aFilePath)
|
const xpstring* aFilePath
|
||||||
|
#endif
|
||||||
|
)
|
||||||
{
|
{
|
||||||
nsCOMPtr<nsILocalFile> minidump;
|
nsCOMPtr<nsILocalFile> minidump;
|
||||||
nsCOMPtr<nsILocalFile> extraFile;
|
nsCOMPtr<nsILocalFile> extraFile;
|
||||||
|
|
||||||
CreateFileFromPath(*aFilePath, getter_AddRefs(minidump));
|
CreateFileFromPath(
|
||||||
|
#ifdef XP_MACOSX
|
||||||
|
aFilePath,
|
||||||
|
#else
|
||||||
|
*aFilePath,
|
||||||
|
#endif
|
||||||
|
getter_AddRefs(minidump));
|
||||||
|
|
||||||
if (!WriteExtraForMinidump(minidump,
|
if (!WriteExtraForMinidump(minidump,
|
||||||
Blacklist(kSubprocessBlacklist,
|
Blacklist(kSubprocessBlacklist,
|
||||||
@@ -1490,13 +1497,17 @@ OnChildProcessDumpRequested(void* aContext,
|
|||||||
MoveToPending(minidump, extraFile);
|
MoveToPending(minidump, extraFile);
|
||||||
|
|
||||||
{
|
{
|
||||||
PRUint32 pid = aClientInfo->pid();
|
PRUint32 pid =
|
||||||
|
#ifdef XP_MACOSX
|
||||||
|
aClientInfo.pid();
|
||||||
|
#else
|
||||||
|
aClientInfo->pid();
|
||||||
|
#endif
|
||||||
|
|
||||||
MutexAutoLock lock(*dumpMapLock);
|
MutexAutoLock lock(*dumpMapLock);
|
||||||
pidToMinidump->Put(pid, minidump);
|
pidToMinidump->Put(pid, minidump);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif // XP_MACOSX
|
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
OOPInitialized()
|
OOPInitialized()
|
||||||
@@ -1539,12 +1550,23 @@ OOPInit()
|
|||||||
NULL, NULL, // we don't care about process exit here
|
NULL, NULL, // we don't care about process exit here
|
||||||
true, // automatically generate dumps
|
true, // automatically generate dumps
|
||||||
&dumpPath);
|
&dumpPath);
|
||||||
|
|
||||||
|
#elif defined(XP_MACOSX)
|
||||||
|
childCrashNotifyPipe =
|
||||||
|
PR_smprintf("gecko-crash-server-pipe.%i",
|
||||||
|
static_cast<int>(getpid()));
|
||||||
|
const std::string dumpPath = gExceptionHandler->dump_path();
|
||||||
|
|
||||||
|
crashServer = new CrashGenerationServer(
|
||||||
|
childCrashNotifyPipe,
|
||||||
|
OnChildProcessDumpRequested, NULL,
|
||||||
|
NULL, NULL,
|
||||||
|
true, // automatically generate dumps
|
||||||
|
dumpPath);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if !defined(XP_MACOSX)
|
|
||||||
if (!crashServer->Start())
|
if (!crashServer->Start())
|
||||||
NS_RUNTIMEABORT("can't start crash reporter server()");
|
NS_RUNTIMEABORT("can't start crash reporter server()");
|
||||||
#endif
|
|
||||||
|
|
||||||
pidToMinidump = new ChildMinidumpMap();
|
pidToMinidump = new ChildMinidumpMap();
|
||||||
pidToMinidump->Init();
|
pidToMinidump->Init();
|
||||||
@@ -1560,10 +1582,8 @@ OOPDeinit()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !defined(XP_MACOSX)
|
|
||||||
delete crashServer;
|
delete crashServer;
|
||||||
crashServer = NULL;
|
crashServer = NULL;
|
||||||
#endif
|
|
||||||
|
|
||||||
delete dumpMapLock;
|
delete dumpMapLock;
|
||||||
dumpMapLock = NULL;
|
dumpMapLock = NULL;
|
||||||
@@ -1577,7 +1597,7 @@ OOPDeinit()
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(XP_WIN)
|
#if defined(XP_WIN) || defined(XP_MACOSX)
|
||||||
// Parent-side API for children
|
// Parent-side API for children
|
||||||
const char*
|
const char*
|
||||||
GetChildNotificationPipe()
|
GetChildNotificationPipe()
|
||||||
@@ -1590,7 +1610,9 @@ GetChildNotificationPipe()
|
|||||||
|
|
||||||
return childCrashNotifyPipe;
|
return childCrashNotifyPipe;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(XP_WIN)
|
||||||
// Child-side API
|
// Child-side API
|
||||||
bool
|
bool
|
||||||
SetRemoteExceptionHandler(const nsACString& crashPipe)
|
SetRemoteExceptionHandler(const nsACString& crashPipe)
|
||||||
@@ -1657,11 +1679,26 @@ SetRemoteExceptionHandler()
|
|||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
#elif defined(XP_MACOSX)
|
#elif defined(XP_MACOSX)
|
||||||
void
|
// Child-side API
|
||||||
CreateNotificationPipeForChild()
|
bool
|
||||||
|
SetRemoteExceptionHandler(const nsACString& crashPipe)
|
||||||
{
|
{
|
||||||
if (GetEnabled() && !OOPInitialized())
|
// crash reporting is disabled
|
||||||
OOPInit();
|
if (crashPipe.Equals(kNullNotifyPipe))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
NS_ABORT_IF_FALSE(!gExceptionHandler, "crash client already init'd");
|
||||||
|
|
||||||
|
gExceptionHandler = new google_breakpad::
|
||||||
|
ExceptionHandler("",
|
||||||
|
NULL, // no filter callback
|
||||||
|
NULL, // no minidump callback
|
||||||
|
NULL, // no callback context
|
||||||
|
true, // install signal handlers
|
||||||
|
crashPipe.BeginReading());
|
||||||
|
|
||||||
|
// we either do remote or nothing, no fallback to regular crash reporting
|
||||||
|
return gExceptionHandler->IsOutOfProcess();
|
||||||
}
|
}
|
||||||
#endif // XP_WIN
|
#endif // XP_WIN
|
||||||
|
|
||||||
@@ -1726,7 +1763,7 @@ CurrentThreadId()
|
|||||||
#elif defined(XP_LINUX)
|
#elif defined(XP_LINUX)
|
||||||
return sys_gettid();
|
return sys_gettid();
|
||||||
#elif defined(XP_MACOSX)
|
#elif defined(XP_MACOSX)
|
||||||
return -1;
|
return mach_thread_self();
|
||||||
#else
|
#else
|
||||||
# error "Unsupported platform"
|
# error "Unsupported platform"
|
||||||
#endif
|
#endif
|
||||||
@@ -1739,12 +1776,11 @@ CreatePairedMinidumps(ProcessHandle childPid,
|
|||||||
nsILocalFile** childDump,
|
nsILocalFile** childDump,
|
||||||
nsILocalFile** parentDump)
|
nsILocalFile** parentDump)
|
||||||
{
|
{
|
||||||
if (!GetEnabled())
|
#ifdef XP_MACOSX
|
||||||
return false;
|
|
||||||
|
|
||||||
#if defined(XP_MACOSX)
|
|
||||||
return false;
|
return false;
|
||||||
#else
|
#else
|
||||||
|
if (!GetEnabled())
|
||||||
|
return false;
|
||||||
|
|
||||||
// create the UUID for the hang dump as a pair
|
// create the UUID for the hang dump as a pair
|
||||||
nsresult rv;
|
nsresult rv;
|
||||||
@@ -1788,7 +1824,9 @@ CreatePairedMinidumps(ProcessHandle childPid,
|
|||||||
{ &parentMinidump, &parentExtra, parentBlacklist };
|
{ &parentMinidump, &parentExtra, parentBlacklist };
|
||||||
if (!google_breakpad::ExceptionHandler::WriteMinidump(
|
if (!google_breakpad::ExceptionHandler::WriteMinidump(
|
||||||
gExceptionHandler->dump_path(),
|
gExceptionHandler->dump_path(),
|
||||||
|
#ifndef XP_MACOSX
|
||||||
true, // write exception stream
|
true, // write exception stream
|
||||||
|
#endif
|
||||||
PairedDumpCallback,
|
PairedDumpCallback,
|
||||||
&parentCtx))
|
&parentCtx))
|
||||||
return false;
|
return false;
|
||||||
@@ -1805,10 +1843,9 @@ CreatePairedMinidumps(ProcessHandle childPid,
|
|||||||
parentMinidump.swap(*parentDump);
|
parentMinidump.swap(*parentDump);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
#endif // XP_MACOSX
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !defined(XP_MACOSX)
|
|
||||||
bool
|
bool
|
||||||
UnsetRemoteExceptionHandler()
|
UnsetRemoteExceptionHandler()
|
||||||
{
|
{
|
||||||
@@ -1816,7 +1853,6 @@ UnsetRemoteExceptionHandler()
|
|||||||
gExceptionHandler = NULL;
|
gExceptionHandler = NULL;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
#endif // XP_MACOSX
|
|
||||||
|
|
||||||
#endif // MOZ_IPC
|
#endif // MOZ_IPC
|
||||||
|
|
||||||
|
|||||||
@@ -52,6 +52,10 @@
|
|||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(XP_MACOSX)
|
||||||
|
#include <mach/mach.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace CrashReporter {
|
namespace CrashReporter {
|
||||||
nsresult SetExceptionHandler(nsILocalFile* aXREDirectory, bool force=false);
|
nsresult SetExceptionHandler(nsILocalFile* aXREDirectory, bool force=false);
|
||||||
nsresult UnsetExceptionHandler();
|
nsresult UnsetExceptionHandler();
|
||||||
@@ -94,9 +98,13 @@ nsresult SetSubmitReports(PRBool aSubmitReport);
|
|||||||
bool TakeMinidumpForChild(PRUint32 childPid,
|
bool TakeMinidumpForChild(PRUint32 childPid,
|
||||||
nsILocalFile** dump NS_OUTPARAM);
|
nsILocalFile** dump NS_OUTPARAM);
|
||||||
|
|
||||||
#ifdef XP_WIN
|
#if defined(XP_WIN)
|
||||||
typedef HANDLE ProcessHandle;
|
typedef HANDLE ProcessHandle;
|
||||||
typedef DWORD ThreadId;
|
typedef DWORD ThreadId;
|
||||||
|
#elif defined(XP_MACOSX)
|
||||||
|
//FIXME: mach_port_t
|
||||||
|
typedef int ProcessHandle;
|
||||||
|
typedef mach_port_t ThreadId;
|
||||||
#else
|
#else
|
||||||
typedef int ProcessHandle;
|
typedef int ProcessHandle;
|
||||||
typedef int ThreadId;
|
typedef int ThreadId;
|
||||||
@@ -123,7 +131,7 @@ bool CreatePairedMinidumps(ProcessHandle childPid,
|
|||||||
nsILocalFile** childDump NS_OUTPARAM,
|
nsILocalFile** childDump NS_OUTPARAM,
|
||||||
nsILocalFile** parentDump NS_OUTPARAM);
|
nsILocalFile** parentDump NS_OUTPARAM);
|
||||||
|
|
||||||
# if defined(XP_WIN32)
|
# if defined(XP_WIN32) || defined(XP_MACOSX)
|
||||||
// Parent-side API for children
|
// Parent-side API for children
|
||||||
const char* GetChildNotificationPipe();
|
const char* GetChildNotificationPipe();
|
||||||
|
|
||||||
@@ -146,11 +154,6 @@ bool CreateNotificationPipeForChild(int* childCrashFd, int* childCrashRemapFd);
|
|||||||
// Child-side API
|
// Child-side API
|
||||||
bool SetRemoteExceptionHandler();
|
bool SetRemoteExceptionHandler();
|
||||||
|
|
||||||
# elif defined(XP_MACOSX)
|
|
||||||
// When OOP crash reporting is implemented for Mac, it will almost
|
|
||||||
// certainly use the same interface as the linux code above. Until
|
|
||||||
// then, we provide stubs.
|
|
||||||
void CreateNotificationPipeForChild();
|
|
||||||
#endif // XP_WIN32
|
#endif // XP_WIN32
|
||||||
|
|
||||||
bool UnsetRemoteExceptionHandler();
|
bool UnsetRemoteExceptionHandler();
|
||||||
|
|||||||
@@ -258,11 +258,10 @@ XRE_TakeMinidumpForChild(PRUint32 aChildPid, nsILocalFile** aDump)
|
|||||||
return CrashReporter::TakeMinidumpForChild(aChildPid, aDump);
|
return CrashReporter::TakeMinidumpForChild(aChildPid, aDump);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !defined(XP_MACOSX)
|
|
||||||
PRBool
|
PRBool
|
||||||
XRE_SetRemoteExceptionHandler(const char* aPipe/*= 0*/)
|
XRE_SetRemoteExceptionHandler(const char* aPipe/*= 0*/)
|
||||||
{
|
{
|
||||||
#if defined(XP_WIN)
|
#if defined(XP_WIN) || defined(XP_MACOSX)
|
||||||
return CrashReporter::SetRemoteExceptionHandler(nsDependentCString(aPipe));
|
return CrashReporter::SetRemoteExceptionHandler(nsDependentCString(aPipe));
|
||||||
#elif defined(OS_LINUX)
|
#elif defined(OS_LINUX)
|
||||||
return CrashReporter::SetRemoteExceptionHandler();
|
return CrashReporter::SetRemoteExceptionHandler();
|
||||||
@@ -270,7 +269,6 @@ XRE_SetRemoteExceptionHandler(const char* aPipe/*= 0*/)
|
|||||||
# error "OOP crash reporter unsupported on this platform"
|
# error "OOP crash reporter unsupported on this platform"
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
#endif // !XP_MACOSX
|
|
||||||
#endif // if defined(MOZ_CRASHREPORTER)
|
#endif // if defined(MOZ_CRASHREPORTER)
|
||||||
|
|
||||||
#if defined(XP_WIN)
|
#if defined(XP_WIN)
|
||||||
|
|||||||
Reference in New Issue
Block a user