mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-26 14:22:01 +00:00
Bug 516759: Use OOP crash reporting in Gecko. r=luser
--HG-- extra : rebase_source : 1949d23a5ce0c15c266d9e67e6a6be7d650a51df
This commit is contained in:
parent
8ecc380a35
commit
6d065b2d57
@ -54,6 +54,29 @@
|
||||
int
|
||||
main(int argc, char* argv[])
|
||||
{
|
||||
#if defined(MOZ_CRASHREPORTER)
|
||||
if (argc < 2)
|
||||
return 1;
|
||||
const char* const crashReporterArg = argv[--argc];
|
||||
|
||||
# if defined(XP_WIN)
|
||||
// on windows, |crashReporterArg| is the named pipe on which the
|
||||
// server is listening for requests, or "-" if crash reporting is
|
||||
// disabled.
|
||||
if (0 != strcmp("-", crashReporterArg)
|
||||
&& !XRE_SetRemoteExceptionHandler(crashReporterArg))
|
||||
return 1;
|
||||
# elif defined(OS_LINUX)
|
||||
// on POSIX, |crashReporterArg| is "true" if crash reporting is
|
||||
// enabled, false otherwise
|
||||
if (0 != strcmp("false", crashReporterArg)
|
||||
&& !XRE_SetRemoteExceptionHandler())
|
||||
return 1;
|
||||
# else
|
||||
# error "OOP crash reporting unsupported on this platform"
|
||||
# endif
|
||||
#endif // if defined(MOZ_CRASHREPORTER)
|
||||
|
||||
#if defined(XP_WIN) && defined(DEBUG_bent)
|
||||
MessageBox(NULL, L"Hi", L"Hi", MB_OK);
|
||||
#endif
|
||||
|
@ -46,6 +46,11 @@
|
||||
|
||||
#include "prprf.h"
|
||||
|
||||
#if defined(OS_LINUX)
|
||||
# define XP_LINUX 1
|
||||
#endif
|
||||
#include "nsExceptionHandler.h"
|
||||
|
||||
#include "mozilla/ipc/GeckoThread.h"
|
||||
|
||||
using mozilla::MonitorAutoEnter;
|
||||
@ -179,7 +184,7 @@ GeckoChildProcessHost::PerformAsyncLaunch(std::vector<std::string> aExtraOpts)
|
||||
int srcChannelFd, dstChannelFd;
|
||||
channel().GetClientFileDescriptorMapping(&srcChannelFd, &dstChannelFd);
|
||||
mFileMap.push_back(std::pair<int,int>(srcChannelFd, dstChannelFd));
|
||||
|
||||
|
||||
// no need for kProcessChannelID, the child process inherits the
|
||||
// other end of the socketpair() from us
|
||||
|
||||
@ -192,6 +197,22 @@ GeckoChildProcessHost::PerformAsyncLaunch(std::vector<std::string> aExtraOpts)
|
||||
childArgv.push_back(pidstring);
|
||||
childArgv.push_back(childProcessType);
|
||||
|
||||
#if defined(MOZ_CRASHREPORTER)
|
||||
int childCrashFd, childCrashRemapFd;
|
||||
if (!CrashReporter::CreateNotificationPipeForChild(
|
||||
&childCrashFd, &childCrashRemapFd))
|
||||
return false;
|
||||
if (0 <= childCrashFd) {
|
||||
mFileMap.push_back(std::pair<int,int>(childCrashFd, childCrashRemapFd));
|
||||
// "true" == crash reporting enabled
|
||||
childArgv.push_back("true");
|
||||
}
|
||||
else {
|
||||
// "false" == crash reporting disabled
|
||||
childArgv.push_back("false");
|
||||
}
|
||||
#endif
|
||||
|
||||
base::LaunchApp(childArgv, mFileMap, false, &process);
|
||||
|
||||
//--------------------------------------------------
|
||||
@ -214,6 +235,10 @@ GeckoChildProcessHost::PerformAsyncLaunch(std::vector<std::string> aExtraOpts)
|
||||
|
||||
cmdLine.AppendLooseValue(UTF8ToWide(pidstring));
|
||||
cmdLine.AppendLooseValue(UTF8ToWide(childProcessType));
|
||||
#if defined(MOZ_CRASHREPORTER)
|
||||
cmdLine.AppendLooseValue(
|
||||
UTF8ToWide(CrashReporter::GetChildNotificationPipe().BeginReading()));
|
||||
#endif
|
||||
|
||||
base::LaunchApp(cmdLine, false, false, &process);
|
||||
|
||||
|
@ -41,6 +41,8 @@ VPATH = @srcdir@
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
LOCAL_INCLUDES += -I$(topsrcdir)/toolkit/crashreporter
|
||||
|
||||
MODULE = ipc
|
||||
LIBRARY_NAME = mozipc_s
|
||||
FORCE_STATIC_LIB = 1
|
||||
|
@ -48,10 +48,11 @@ LIBRARY_NAME = crash_generation_s
|
||||
LOCAL_INCLUDES = -I$(topsrcdir)/toolkit/crashreporter/google-breakpad/src
|
||||
DEFINES += -DUNICODE -D_UNICODE
|
||||
|
||||
#XXX: We're not currently building the other parts,
|
||||
# which would only be needed on the server side of the equation.
|
||||
CPPSRCS = \
|
||||
client_info.cc \
|
||||
crash_generation_client.cc \
|
||||
crash_generation_server.cc \
|
||||
minidump_generator.cc \
|
||||
$(NULL)
|
||||
|
||||
# need static lib
|
||||
|
@ -43,7 +43,9 @@
|
||||
#undef WIN32_LEAN_AND_MEAN
|
||||
#endif
|
||||
|
||||
#include "client/windows/crash_generation/crash_generation_server.h"
|
||||
#include "client/windows/handler/exception_handler.h"
|
||||
#include <DbgHelp.h>
|
||||
#include <string.h>
|
||||
#elif defined(XP_MACOSX)
|
||||
#include "client/mac/handler/exception_handler.h"
|
||||
@ -54,6 +56,7 @@
|
||||
#include <unistd.h>
|
||||
#include "mac_utils.h"
|
||||
#elif defined(XP_LINUX)
|
||||
#include "client/linux/crash_generation/crash_generation_server.h"
|
||||
#include "client/linux/handler/exception_handler.h"
|
||||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
@ -77,6 +80,9 @@
|
||||
#include "nsILocalFile.h"
|
||||
#include "nsDataHashtable.h"
|
||||
|
||||
using google_breakpad::CrashGenerationServer;
|
||||
using google_breakpad::ClientInfo;
|
||||
|
||||
namespace CrashReporter {
|
||||
|
||||
#ifdef XP_WIN32
|
||||
@ -141,6 +147,22 @@ static nsDataHashtable<nsCStringHashKey,nsCString>* crashReporterAPIData_Hash;
|
||||
static nsCString* crashReporterAPIData = nsnull;
|
||||
static nsCString* notesField = nsnull;
|
||||
|
||||
// OOP crash reporting
|
||||
static CrashGenerationServer* crashServer; // chrome process has this
|
||||
|
||||
#if defined(XP_WIN)
|
||||
// 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.
|
||||
static const char kNullNotifyPipe[] = "-";
|
||||
static nsCString* childCrashNotifyPipe;
|
||||
|
||||
#elif defined(XP_LINUX)
|
||||
static int serverSocketFd = -1;
|
||||
static int clientSocketFd = -1;
|
||||
static const int kMagicChildCrashReportFd = 42;
|
||||
#endif
|
||||
|
||||
|
||||
static XP_CHAR*
|
||||
Concat(XP_CHAR* str, const XP_CHAR* toAppend, int* size)
|
||||
{
|
||||
@ -909,4 +931,158 @@ nsresult AppendObjCExceptionInfoToAppNotes(void *inException)
|
||||
}
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Out-of-process crash reporting API wrappers
|
||||
static void
|
||||
OnChildProcessDumpRequested(void* aContext,
|
||||
const ClientInfo* aClientInfo,
|
||||
#if defined(XP_WIN)
|
||||
const std::wstring*
|
||||
#else
|
||||
const std::string*
|
||||
#endif
|
||||
aFilePath)
|
||||
{
|
||||
printf("CHILD DUMP REQUEST\n");
|
||||
}
|
||||
|
||||
static bool
|
||||
OOPInitialized()
|
||||
{
|
||||
return crashServer != NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
OOPInit()
|
||||
{
|
||||
NS_ABORT_IF_FALSE(!OOPInitialized(),
|
||||
"OOP crash reporter initialized more than once!");
|
||||
NS_ABORT_IF_FALSE(gExceptionHandler != NULL,
|
||||
"attempt to initialize OOP crash reporter before in-process crashreporter!");
|
||||
|
||||
#if defined(XP_WIN)
|
||||
// this is a CString to make it more convenient to pass on the
|
||||
// command line
|
||||
childCrashNotifyPipe =
|
||||
new nsCString("\\\\.\\pipe\\gecko-crash-server-pipe.");
|
||||
long pid = static_cast<long>(::GetCurrentProcessId());
|
||||
childCrashNotifyPipe->AppendInt(pid);
|
||||
|
||||
const std::wstring dumpPath = gExceptionHandler->dump_path();
|
||||
crashServer = new CrashGenerationServer(
|
||||
NS_ConvertASCIItoUTF16(*childCrashNotifyPipe).BeginReading(),
|
||||
NULL, // default security attributes
|
||||
NULL, NULL, // we don't care about process connect here
|
||||
OnChildProcessDumpRequested, NULL,
|
||||
NULL, NULL, // we don't care about process exit here
|
||||
true, // automatically generate dumps
|
||||
&dumpPath);
|
||||
|
||||
#elif defined(XP_LINUX)
|
||||
if (!CrashGenerationServer::CreateReportChannel(&serverSocketFd,
|
||||
&clientSocketFd))
|
||||
NS_RUNTIMEABORT("can't create crash reporter socketpair()");
|
||||
|
||||
const std::string dumpPath = gExceptionHandler->dump_path();
|
||||
crashServer = new CrashGenerationServer(
|
||||
serverSocketFd,
|
||||
OnChildProcessDumpRequested, NULL,
|
||||
NULL, NULL, // we don't care about process exit here
|
||||
true, // automatically generate dumps
|
||||
&dumpPath);
|
||||
#endif
|
||||
|
||||
if (!crashServer->Start())
|
||||
NS_RUNTIMEABORT("can't start crash reporter server()");
|
||||
}
|
||||
|
||||
#if defined(XP_WIN)
|
||||
// Parent-side API for children
|
||||
nsCString
|
||||
GetChildNotificationPipe()
|
||||
{
|
||||
if (!GetEnabled())
|
||||
return nsDependentCString(kNullNotifyPipe);
|
||||
|
||||
if (!OOPInitialized())
|
||||
OOPInit();
|
||||
|
||||
return *childCrashNotifyPipe;
|
||||
}
|
||||
|
||||
// Child-side API
|
||||
bool
|
||||
SetRemoteExceptionHandler(const nsACString& crashPipe)
|
||||
{
|
||||
// crash reporting is disabled
|
||||
if (crashPipe.Equals(kNullNotifyPipe))
|
||||
return true;
|
||||
|
||||
NS_ABORT_IF_FALSE(!gExceptionHandler, "crash client already init'd");
|
||||
|
||||
gExceptionHandler = new google_breakpad::
|
||||
ExceptionHandler(L"",
|
||||
NULL, // no filter callback
|
||||
NULL, // no minidump callback
|
||||
NULL, // no callback context
|
||||
google_breakpad::ExceptionHandler::HANDLER_ALL,
|
||||
MiniDumpNormal,
|
||||
NS_ConvertASCIItoUTF16(crashPipe).BeginReading(),
|
||||
NULL);
|
||||
|
||||
// we either do remote or nothing, no fallback to regular crash reporting
|
||||
return gExceptionHandler->IsOutOfProcess();
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
#elif defined(XP_UNIX)
|
||||
|
||||
// Parent-side API for children
|
||||
bool
|
||||
CreateNotificationPipeForChild(int* childCrashFd, int* childCrashRemapFd)
|
||||
{
|
||||
if (!GetEnabled()) {
|
||||
*childCrashFd = -1;
|
||||
*childCrashRemapFd = -1;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!OOPInitialized())
|
||||
OOPInit();
|
||||
|
||||
*childCrashFd = clientSocketFd;
|
||||
*childCrashRemapFd = kMagicChildCrashReportFd;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Child-side API
|
||||
bool
|
||||
SetRemoteExceptionHandler()
|
||||
{
|
||||
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
|
||||
kMagicChildCrashReportFd);
|
||||
|
||||
// we either do remote or nothing, no fallback to regular crash reporting
|
||||
return gExceptionHandler->IsOutOfProcess();
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
bool
|
||||
UnsetRemoteExceptionHandler()
|
||||
{
|
||||
delete gExceptionHandler;
|
||||
gExceptionHandler = NULL;
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace CrashReporter
|
||||
|
@ -64,10 +64,33 @@ nsresult SetupExtraData(nsILocalFile* aAppDataDirectory,
|
||||
const nsACString& aBuildID);
|
||||
#ifdef XP_WIN32
|
||||
nsresult WriteMinidumpForException(EXCEPTION_POINTERS* aExceptionInfo);
|
||||
|
||||
// Parent-side API for children
|
||||
nsCString GetChildNotificationPipe();
|
||||
// Child-side API
|
||||
bool SetRemoteExceptionHandler(const nsACString& crashPipe);
|
||||
#endif
|
||||
#ifdef XP_MACOSX
|
||||
nsresult AppendObjCExceptionInfoToAppNotes(void *inException);
|
||||
#endif
|
||||
#ifdef XP_LINUX
|
||||
// Parent-side API for children
|
||||
|
||||
// Set the outparams for crash reporter server's fd (|childCrashFd|)
|
||||
// and the magic fd number it should be remapped to
|
||||
// (|childCrashRemapFd|) before exec() in the child process.
|
||||
// |SetRemoteExceptionHandler()| in the child process expects to find
|
||||
// the server at |childCrashRemapFd|. Return true iff successful.
|
||||
//
|
||||
// If crash reporting is disabled, both outparams will be set to -1
|
||||
// and |true| will be returned.
|
||||
bool CreateNotificationPipeForChild(int* childCrashFd, int* childCrashRemapFd);
|
||||
|
||||
// Child-side API
|
||||
bool SetRemoteExceptionHandler();
|
||||
#endif
|
||||
|
||||
bool UnsetRemoteExceptionHandler();
|
||||
}
|
||||
|
||||
#endif /* nsExceptionHandler_h__ */
|
||||
|
@ -174,7 +174,10 @@ include $(topsrcdir)/config/config.mk
|
||||
include $(topsrcdir)/ipc/chromium/chromium-config.mk
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
LOCAL_INCLUDES += -I$(topsrcdir)/dom/ipc
|
||||
LOCAL_INCLUDES += \
|
||||
-I$(topsrcdir)/dom/ipc \
|
||||
-I$(topsrcdir)/toolkit/crashreporter \
|
||||
$(NULL)
|
||||
|
||||
ifdef BUILD_STATIC_LIBS
|
||||
export::
|
||||
|
@ -55,10 +55,15 @@
|
||||
#include "nsIToolkitChromeRegistry.h"
|
||||
#include "nsIToolkitProfile.h"
|
||||
|
||||
#if defined(OS_LINUX)
|
||||
# define XP_LINUX
|
||||
#endif
|
||||
|
||||
#include "nsAppDirectoryServiceDefs.h"
|
||||
#include "nsAppRunner.h"
|
||||
#include "nsAutoRef.h"
|
||||
#include "nsDirectoryServiceDefs.h"
|
||||
#include "nsExceptionHandler.h"
|
||||
#include "nsStaticComponents.h"
|
||||
#include "nsString.h"
|
||||
#include "nsThreadUtils.h"
|
||||
@ -242,6 +247,20 @@ GeckoProcessType sChildProcessType = GeckoProcessType_Default;
|
||||
|
||||
static MessageLoop* sIOMessageLoop;
|
||||
|
||||
#if defined(MOZ_CRASHREPORTER)
|
||||
PRBool
|
||||
XRE_SetRemoteExceptionHandler(const char* aPipe/*= 0*/)
|
||||
{
|
||||
#if defined(XP_WIN)
|
||||
return CrashReporter::SetRemoteExceptionHandler(nsDependentCString(aPipe));
|
||||
#elif defined(OS_LINUX)
|
||||
return CrashReporter::SetRemoteExceptionHandler();
|
||||
#else
|
||||
# error "OOP crash reporter unsupported on this platform"
|
||||
#endif
|
||||
}
|
||||
#endif // if defined(MOZ_CRASHREPORTER)
|
||||
|
||||
nsresult
|
||||
XRE_InitChildProcess(int aArgc,
|
||||
char* aArgv[],
|
||||
|
@ -449,6 +449,11 @@ XRE_API(const char*,
|
||||
XRE_API(GeckoProcessType,
|
||||
XRE_StringToChildProcessType, (const char* aProcessTypeString))
|
||||
|
||||
#if defined(MOZ_CRASHREPORTER)
|
||||
XRE_API(PRBool,
|
||||
XRE_SetRemoteExceptionHandler, (const char* aPipe=0))
|
||||
#endif
|
||||
|
||||
XRE_API(nsresult,
|
||||
XRE_InitChildProcess, (int aArgc,
|
||||
char* aArgv[],
|
||||
|
Loading…
Reference in New Issue
Block a user