Merge m-c to inbound.

This commit is contained in:
Ryan VanderMeulen 2012-07-12 21:12:17 -04:00
commit 1b61fbb7ca
16 changed files with 282 additions and 139 deletions

View File

@ -3,7 +3,7 @@
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
llvm_revision = "159409"
llvm_revision = "160105"
moz_version = "moz0"
##############################################

View File

@ -191,7 +191,7 @@ endif
profiledbuild::
$(MAKE) -f $(TOPSRCDIR)/client.mk realbuild MOZ_PROFILE_GENERATE=1 MOZ_PGO_INSTRUMENTED=1
$(MAKE) -C $(PGO_OBJDIR) stage-package MOZ_PGO_INSTRUMENTED=1
$(MAKE) -C $(PGO_OBJDIR) package MOZ_PGO_INSTRUMENTED=1 MOZ_INTERNAL_SIGNING_FORMAT= MOZ_EXTERNAL_SIGNING_FORMAT=
MOZ_PGO_INSTRUMENTED=1 OBJDIR=${PGO_OBJDIR} JARLOG_DIR=${PGO_OBJDIR}/jarlog/en-US $(PROFILE_GEN_SCRIPT)
$(MAKE) -f $(TOPSRCDIR)/client.mk maybe_clobber_profiledbuild
$(MAKE) -f $(TOPSRCDIR)/client.mk realbuild MOZ_PROFILE_USE=1

View File

@ -98,6 +98,15 @@ CrashReporterParent::GenerateHangCrashReport(const AnnotationTable* processNotes
return true;
}
bool
CrashReporterParent::GenerateCrashReportForMinidump(nsIFile* minidump,
const AnnotationTable* processNotes)
{
if (!CrashReporter::GetIDFromMinidump(minidump, mChildDumpID))
return false;
return GenerateChildData(processNotes);
}
bool
CrashReporterParent::GenerateChildData(const AnnotationTable* processNotes)
{

View File

@ -49,6 +49,10 @@ public:
bool
GenerateCrashReport(Toplevel* t, const AnnotationTable* processNotes);
bool
GenerateCrashReportForMinidump(nsIFile* minidump,
const AnnotationTable* processNotes);
/* Instantiate a new crash reporter actor from a given parent that manages
the protocol.
*/
@ -135,7 +139,7 @@ CrashReporterParent::GenerateCrashReport(Toplevel* t,
const AnnotationTable* processNotes)
{
nsCOMPtr<nsIFile> crashDump;
if (t->TakeMinidump(getter_AddRefs(crashDump)) &&
if (t->TakeMinidump(getter_AddRefs(crashDump), NULL) &&
CrashReporter::GetIDFromMinidump(crashDump, mChildDumpID)) {
return GenerateChildData(processNotes);
}

View File

@ -27,9 +27,6 @@
#include "nsAutoPtr.h"
#include "nsCRT.h"
#ifdef MOZ_CRASHREPORTER
#include "mozilla/dom/CrashReporterParent.h"
#endif
#include "nsNPAPIPlugin.h"
#include "nsIFile.h"
@ -49,6 +46,12 @@ using namespace mozilla;
using namespace mozilla::plugins;
using namespace mozilla::plugins::parent;
#ifdef MOZ_CRASHREPORTER
#include "mozilla/dom/CrashReporterParent.h"
using namespace CrashReporter;
#endif
static const char kChildTimeoutPref[] = "dom.ipc.plugins.timeoutSecs";
static const char kParentTimeoutPref[] = "dom.ipc.plugins.parentTimeoutSecs";
static const char kLaunchTimeoutPref[] = "dom.ipc.plugins.processLaunchTimeoutSecs";
@ -133,9 +136,9 @@ PluginModuleParent::~PluginModuleParent()
#ifdef MOZ_CRASHREPORTER_INJECTOR
if (mFlashProcess1)
CrashReporter::UnregisterInjectorCallback(mFlashProcess1);
UnregisterInjectorCallback(mFlashProcess1);
if (mFlashProcess2)
CrashReporter::UnregisterInjectorCallback(mFlashProcess2);
UnregisterInjectorCallback(mFlashProcess2);
#endif
Preferences::UnregisterCallback(TimeoutChanged, kChildTimeoutPref, this);
@ -144,7 +147,7 @@ PluginModuleParent::~PluginModuleParent()
#ifdef MOZ_CRASHREPORTER
void
PluginModuleParent::WriteExtraDataForMinidump(CrashReporter::AnnotationTable& notes)
PluginModuleParent::WriteExtraDataForMinidump(AnnotationTable& notes)
{
typedef nsDependentCString CS;
@ -200,19 +203,17 @@ bool
PluginModuleParent::ShouldContinueFromReplyTimeout()
{
#ifdef MOZ_CRASHREPORTER
if (mPluginDumpID.IsEmpty()) {
CrashReporterParent* crashReporter = CrashReporter();
if (crashReporter->GeneratePairedMinidump(this)) {
mBrowserDumpID = crashReporter->ParentDumpID();
mPluginDumpID = crashReporter->ChildDumpID();
PLUGIN_LOG_DEBUG(
("generated paired browser/plugin minidumps: %s/%s (ID=%s)",
NS_ConvertUTF16toUTF8(mBrowserDumpID).get(),
NS_ConvertUTF16toUTF8(mPluginDumpID).get(),
NS_ConvertUTF16toUTF8(crashReporter->HangID()).get()));
} else {
NS_WARNING("failed to capture paired minidumps from hang");
}
CrashReporterParent* crashReporter = CrashReporter();
if (crashReporter->GeneratePairedMinidump(this)) {
mBrowserDumpID = crashReporter->ParentDumpID();
mPluginDumpID = crashReporter->ChildDumpID();
PLUGIN_LOG_DEBUG(
("generated paired browser/plugin minidumps: %s/%s (ID=%s)",
NS_ConvertUTF16toUTF8(mBrowserDumpID).get(),
NS_ConvertUTF16toUTF8(mPluginDumpID).get(),
NS_ConvertUTF16toUTF8(crashReporter->HangID()).get()));
} else {
NS_WARNING("failed to capture paired minidumps from hang");
}
#endif
@ -237,33 +238,99 @@ PluginModuleParent::CrashReporter()
}
#endif
#ifdef MOZ_CRASHREPORTER
static void
RemoveMinidump(nsIFile* minidump)
{
if (!minidump)
return;
minidump->Remove(false);
nsCOMPtr<nsIFile> extraFile;
if (GetExtraFileForMinidump(minidump,
getter_AddRefs(extraFile))) {
extraFile->Remove(true);
}
}
void
PluginModuleParent::ProcessFirstMinidump()
{
CrashReporterParent* crashReporter = CrashReporter();
if (!crashReporter)
return;
AnnotationTable notes;
notes.Init(4);
WriteExtraDataForMinidump(notes);
if (!mPluginDumpID.IsEmpty() && !mBrowserDumpID.IsEmpty()) {
crashReporter->GenerateHangCrashReport(&notes);
return;
}
PRUint32 sequence = PR_UINT32_MAX;
nsCOMPtr<nsIFile> dumpFile;
nsCAutoString flashProcessType;
TakeMinidump(getter_AddRefs(dumpFile), &sequence);
#ifdef MOZ_CRASHREPORTER_INJECTOR
nsCOMPtr<nsIFile> childDumpFile;
PRUint32 childSequence;
if (mFlashProcess1 &&
TakeMinidumpForChild(mFlashProcess1,
getter_AddRefs(childDumpFile),
&childSequence)) {
if (childSequence < sequence) {
RemoveMinidump(dumpFile);
dumpFile = childDumpFile;
sequence = childSequence;
flashProcessType.AssignLiteral("Broker");
}
else {
RemoveMinidump(childDumpFile);
}
}
if (mFlashProcess2 &&
TakeMinidumpForChild(mFlashProcess2,
getter_AddRefs(childDumpFile),
&childSequence)) {
if (childSequence < sequence) {
RemoveMinidump(dumpFile);
dumpFile = childDumpFile;
sequence = childSequence;
flashProcessType.AssignLiteral("Sandbox");
}
else {
RemoveMinidump(childDumpFile);
}
}
#endif
if (!dumpFile) {
NS_WARNING("[PluginModuleParent::ActorDestroy] abnormal shutdown without minidump!");
return;
}
PLUGIN_LOG_DEBUG(("got child minidump: %s",
NS_ConvertUTF16toUTF8(mPluginDumpID).get()));
GetIDFromMinidump(dumpFile, mPluginDumpID);
if (!flashProcessType.IsEmpty()) {
notes.Put(NS_LITERAL_CSTRING("FlashProcessDump"), flashProcessType);
}
crashReporter->GenerateCrashReportForMinidump(dumpFile, &notes);
}
#endif
void
PluginModuleParent::ActorDestroy(ActorDestroyReason why)
{
switch (why) {
case AbnormalShutdown: {
#ifdef MOZ_CRASHREPORTER
CrashReporterParent* crashReporter = CrashReporter();
CrashReporter::AnnotationTable notes;
notes.Init(4);
WriteExtraDataForMinidump(notes);
if (!mPluginDumpID.IsEmpty() && !mBrowserDumpID.IsEmpty()) {
crashReporter->GenerateHangCrashReport(&notes);
}
else if (!mPluginDumpID.IsEmpty()) {
// Nothing to do, we've already written this minidump in
// PluginModuleParent::OnCrash
}
else if (crashReporter->GenerateCrashReport(this, &notes)) {
mPluginDumpID = crashReporter->ChildDumpID();
PLUGIN_LOG_DEBUG(("got child minidump: %s",
NS_ConvertUTF16toUTF8(mPluginDumpID).get()));
}
else {
NS_WARNING("[PluginModuleParent::ActorDestroy] abnormal shutdown without minidump!");
}
ProcessFirstMinidump();
#endif
mShutdown = true;
@ -1248,33 +1315,8 @@ PluginModuleParent::InitializeInjector()
}
void
PluginModuleParent::OnCrash(DWORD processID, const nsAString& aDumpID)
PluginModuleParent::OnCrash(DWORD processID)
{
if (!mPluginDumpID.IsEmpty()) {
// One process has already crashed: we assume that the first-to-crash
// is the interesting one
return;
}
mPluginDumpID = aDumpID;
CrashReporter::AnnotationTable notes;
notes.Init(4);
WriteExtraDataForMinidump(notes);
notes.Put(NS_LITERAL_CSTRING("ProcessType"), NS_LITERAL_CSTRING("plugin"));
if (processID == mFlashProcess1) {
notes.Put(NS_LITERAL_CSTRING("FlashProcessDump"),
NS_LITERAL_CSTRING("Broker"));
}
else if (processID == mFlashProcess2) {
notes.Put(NS_LITERAL_CSTRING("FlashProcessDump"),
NS_LITERAL_CSTRING("Sandbox"));
}
else {
NS_ERROR("Got minidump for Flash process neither broker nor sandbox.");
}
CrashReporter::AppendExtraData(aDumpID, notes);
GetIPCChannel()->CloseWithError();
KillProcess(OtherProcess(), 1, false);
}

View File

@ -288,6 +288,7 @@ private:
CrashReporterParent* CrashReporter();
#ifdef MOZ_CRASHREPORTER
void ProcessFirstMinidump();
void WriteExtraDataForMinidump(CrashReporter::AnnotationTable& notes);
#endif
void CleanupFromTimeout();
@ -319,7 +320,7 @@ private:
#ifdef MOZ_CRASHREPORTER_INJECTOR
void InitializeInjector();
NS_OVERRIDE void OnCrash(DWORD processID, const nsAString& aDumpID);
NS_OVERRIDE void OnCrash(DWORD processID);
DWORD mFlashProcess1;
DWORD mFlashProcess2;

View File

@ -253,6 +253,10 @@ void GeckoChildProcessHost::InitWindowsGroupID()
bool
GeckoChildProcessHost::SyncLaunch(std::vector<std::string> aExtraOpts, int aTimeoutMs, base::ProcessArchitecture arch)
{
#ifdef MOZ_CRASHREPORTER
CrashReporter::OOPInit();
#endif
#ifdef XP_WIN
InitWindowsGroupID();
#endif
@ -294,6 +298,10 @@ GeckoChildProcessHost::SyncLaunch(std::vector<std::string> aExtraOpts, int aTime
bool
GeckoChildProcessHost::AsyncLaunch(std::vector<std::string> aExtraOpts)
{
#ifdef MOZ_CRASHREPORTER
CrashReporter::OOPInit();
#endif
#ifdef XP_WIN
InitWindowsGroupID();
#endif

View File

@ -330,6 +330,7 @@ Type.INT = Type('int')
Type.INT32 = Type('int32')
Type.INTPTR = Type('intptr_t')
Type.UINT32 = Type('uint32')
Type.UINT32PTR = Type('uint32', ptr=1)
Type.SIZE = Type('size_t')
Type.VOID = Type('void')
Type.VOIDPTR = Type('void', ptr=1)

View File

@ -3089,16 +3089,18 @@ class _GenerateProtocolActorCode(ipdl.ast.Visitor):
])
dumpvar = ExprVar('aDump')
seqvar = ExprVar('aSequence')
getdump = MethodDefn(MethodDecl(
'TakeMinidump',
params=[ Decl(Type('nsIFile', ptrptr=1), dumpvar.name) ],
params=[ Decl(Type('nsIFile', ptrptr=1), dumpvar.name),
Decl(Type.UINT32PTR, seqvar.name)],
ret=Type.BOOL,
const=1))
getdump.addstmts([
CppDirective('ifdef', 'MOZ_CRASHREPORTER'),
StmtReturn(ExprCall(
ExprVar('XRE_TakeMinidumpForChild'),
args=[ ExprCall(otherpidvar), dumpvar ])),
args=[ ExprCall(otherpidvar), dumpvar, seqvar ])),
CppDirective('else'),
StmtReturn.FALSE,
CppDirective('endif')

View File

@ -169,7 +169,7 @@ FENNEC_PP_XML_FILES = \
res/menu/gecko_menu.xml \
res/menu-v11/gecko_menu.xml \
res/menu-v11/titlebar_contextmenu.xml \
res/menu-large/gecko_menu.xml \
res/menu-large-v11/gecko_menu.xml \
$(NULL)
@ -941,7 +941,11 @@ RES_DIRS= \
res/color \
res/menu \
res/menu-v11 \
<<<<<<< local
res/menu-large \
=======
res/menu-large-v11 \
>>>>>>> other
$(NULL)

View File

@ -23,6 +23,7 @@
#include "client/windows/handler/exception_handler.h"
#include <DbgHelp.h>
#include <string.h>
#include "nsDirectoryServiceUtils.h"
#include "nsWindowsDllInterceptor.h"
#elif defined(XP_MACOSX)
@ -40,7 +41,6 @@
#include <unistd.h>
#include "mac_utils.h"
#elif defined(XP_LINUX)
#include "nsDirectoryServiceUtils.h"
#include "nsDirectoryServiceDefs.h"
#include "nsIINIParser.h"
#include "common/linux/linux_libc_support.h"
@ -152,6 +152,7 @@ static const XP_CHAR extraFileExtension[] = {'.', 'e', 'x', 't',
static google_breakpad::ExceptionHandler* gExceptionHandler = nsnull;
static XP_CHAR* pendingDirectory;
static XP_CHAR* crashReporterPath;
// if this is false, we don't launch the crash reporter
@ -221,13 +222,32 @@ static const int kMagicChildCrashReportFd = 4;
// |dumpMapLock| must protect all access to |pidToMinidump|.
static Mutex* dumpMapLock;
typedef nsInterfaceHashtable<nsUint32HashKey, nsIFile> ChildMinidumpMap;
struct ChildProcessData : public nsUint32HashKey
{
ChildProcessData(KeyTypePointer aKey)
: nsUint32HashKey(aKey)
, sequence(0)
#ifdef MOZ_CRASHREPORTER_INJECTOR
, callback(NULL)
#endif
{ }
nsCOMPtr<nsIFile> minidump;
// Each crashing process is assigned an increasing sequence number to
// indicate which process crashed first.
PRUint32 sequence;
#ifdef MOZ_CRASHREPORTER_INJECTOR
InjectorCrashCallback* callback;
#endif
};
typedef nsTHashtable<ChildProcessData> ChildMinidumpMap;
static ChildMinidumpMap* pidToMinidump;
static PRUint32 crashSequence;
static bool OOPInitialized();
#ifdef MOZ_CRASHREPORTER_INJECTOR
static nsIThread* sInjectorThread;
typedef nsDataHashtable<nsUint32HashKey, InjectorCrashCallback*> InjectorPIDMap;
static InjectorPIDMap* pidToInjectorCallback;
class ReportInjectedCrash : public nsRunnable
{
@ -714,13 +734,13 @@ nsresult SetExceptionHandler(nsIFile* aXREDirectory,
#ifdef XP_WIN32
nsString crashReporterPath_temp;
exePath->GetPath(crashReporterPath_temp);
exePath->GetPath(crashReporterPath_temp);
crashReporterPath = ToNewUnicode(crashReporterPath_temp);
#elif !defined(__ANDROID__)
nsCString crashReporterPath_temp;
exePath->GetNativePath(crashReporterPath_temp);
exePath->GetNativePath(crashReporterPath_temp);
crashReporterPath = ToNewCString(crashReporterPath_temp);
#else
// On Android, we launch using the application package name
@ -1133,6 +1153,11 @@ nsresult UnsetExceptionHandler()
delete notesField;
notesField = nsnull;
if (pendingDirectory) {
NS_Free(pendingDirectory);
pendingDirectory = nsnull;
}
if (crashReporterPath) {
NS_Free(crashReporterPath);
crashReporterPath = nsnull;
@ -1671,23 +1696,23 @@ nsresult SetSubmitReports(bool aSubmitReports)
}
// The "pending" dir is Crash Reports/pending, from which minidumps
// can be submitted
// can be submitted. Because this method may be called off the main thread,
// we store the pending directory as a path.
static bool
GetPendingDir(nsIFile** dir)
{
nsCOMPtr<nsIProperties> dirSvc =
do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID);
if (!dirSvc)
MOZ_ASSERT(OOPInitialized());
if (!pendingDirectory) {
return false;
nsCOMPtr<nsIFile> pendingDir;
if (NS_FAILED(dirSvc->Get("UAppData",
NS_GET_IID(nsIFile),
getter_AddRefs(pendingDir))) ||
NS_FAILED(pendingDir->Append(NS_LITERAL_STRING("Crash Reports"))) ||
NS_FAILED(pendingDir->Append(NS_LITERAL_STRING("pending"))))
return false;
*dir = NULL;
pendingDir.swap(*dir);
}
nsCOMPtr<nsIFile> pending = do_CreateInstance(NS_LOCAL_FILE_CONTRACTID);
#ifdef XP_WIN
pending->InitWithPath(nsDependentString(pendingDirectory));
#else
pending->InitWithNativePath(nsDependentCString(pendingDirectory));
#endif
pending.swap(*dir);
return true;
}
@ -1952,12 +1977,22 @@ OnChildProcessDumpRequested(void* aContext,
aClientInfo->pid();
#endif
#ifdef MOZ_CRASHREPORTER_INJECTOR
bool runCallback;
#endif
{
MutexAutoLock lock(*dumpMapLock);
pidToMinidump->Put(pid, minidump);
ChildProcessData* pd = pidToMinidump->PutEntry(pid);
MOZ_ASSERT(!pd->minidump);
pd->minidump = minidump;
pd->sequence = ++crashSequence;
#ifdef MOZ_CRASHREPORTER_INJECTOR
runCallback = NULL != pd->callback;
#endif
}
#ifdef MOZ_CRASHREPORTER_INJECTOR
NS_DispatchToMainThread(new ReportInjectedCrash(pid));
if (runCallback)
NS_DispatchToMainThread(new ReportInjectedCrash(pid));
#endif
}
}
@ -1973,11 +2008,14 @@ static bool ChildFilter(void *context) {
return true;
}
static void
void
OOPInit()
{
NS_ABORT_IF_FALSE(!OOPInitialized(),
"OOP crash reporter initialized more than once!");
if (OOPInitialized())
return;
MOZ_ASSERT(NS_IsMainThread());
NS_ABORT_IF_FALSE(gExceptionHandler != NULL,
"attempt to initialize OOP crash reporter before in-process crashreporter!");
@ -2038,6 +2076,26 @@ OOPInit()
pidToMinidump->Init();
dumpMapLock = new Mutex("CrashReporter::dumpMapLock");
nsCOMPtr<nsIFile> pendingDir;
nsresult rv = NS_GetSpecialDirectory("UAppData", getter_AddRefs(pendingDir));
if (NS_FAILED(rv)) {
NS_WARNING("Couldn't get the user appdata directory, crash dumps will go in an unusual location");
}
else {
pendingDir->Append(NS_LITERAL_STRING("Crash Reports"));
pendingDir->Append(NS_LITERAL_STRING("pending"));
#ifdef XP_WIN
nsString path;
pendingDir->GetPath(path);
pendingDirectory = ToNewUnicode(path);
#else
nsCString path;
pendingDir->GetNativePath(path);
pendingDirectory = ToNewCString(path);
#endif
}
}
static void
@ -2053,9 +2111,6 @@ OOPDeinit()
sInjectorThread->Shutdown();
NS_RELEASE(sInjectorThread);
}
delete pidToInjectorCallback;
pidToInjectorCallback = NULL;
#endif
delete crashServer;
@ -2081,8 +2136,7 @@ GetChildNotificationPipe()
if (!GetEnabled())
return kNullNotifyPipe;
if (!OOPInitialized())
OOPInit();
MOZ_ASSERT(OOPInitialized());
return childCrashNotifyPipe;
}
@ -2098,17 +2152,17 @@ InjectCrashReporterIntoProcess(DWORD processID, InjectorCrashCallback* cb)
if (!OOPInitialized())
OOPInit();
if (!pidToInjectorCallback) {
pidToInjectorCallback = new InjectorPIDMap;
pidToInjectorCallback->Init();
}
if (!sInjectorThread) {
if (NS_FAILED(NS_NewThread(&sInjectorThread)))
return;
}
pidToInjectorCallback->Put(processID, cb);
{
MutexAutoLock lock(*dumpMapLock);
ChildProcessData* pd = pidToMinidump->PutEntry(processID);
MOZ_ASSERT(!pd->minidump && !pd->callback);
pd->callback = cb;
}
nsCOMPtr<nsIRunnable> r = new InjectCrashRunnable(processID);
sInjectorThread->Dispatch(r, nsIEventTarget::DISPATCH_NORMAL);
@ -2118,23 +2172,22 @@ NS_IMETHODIMP
ReportInjectedCrash::Run()
{
// Crash reporting may have been disabled after this method was dispatched
if (!pidToInjectorCallback)
if (!OOPInitialized())
return NS_OK;
InjectorCrashCallback* cb = pidToInjectorCallback->Get(mPID);
if (!cb)
return NS_OK;
InjectorCrashCallback* cb;
{
MutexAutoLock lock(*dumpMapLock);
ChildProcessData* pd = pidToMinidump->GetEntry(mPID);
if (!pd || !pd->callback)
return NS_OK;
nsCOMPtr<nsIFile> minidump;
if (!TakeMinidumpForChild(mPID, getter_AddRefs(minidump))) {
NS_WARNING("No minidump for crash notification.");
return NS_OK;
MOZ_ASSERT(pd->minidump);
cb = pd->callback;
}
nsString id;
GetIDFromMinidump(minidump, id);
cb->OnCrash(mPID, id);
cb->OnCrash(mPID);
return NS_OK;
}
@ -2144,7 +2197,8 @@ UnregisterInjectorCallback(DWORD processID)
if (!OOPInitialized())
return;
pidToInjectorCallback->Remove(processID);
MutexAutoLock lock(*dumpMapLock);
pidToMinidump->RemoveEntry(processID);
}
#endif // MOZ_CRASHREPORTER_INJECTOR
@ -2190,8 +2244,7 @@ CreateNotificationPipeForChild(int* childCrashFd, int* childCrashRemapFd)
return true;
}
if (!OOPInitialized())
OOPInit();
MOZ_ASSERT(OOPInitialized());
*childCrashFd = clientSocketFd;
*childCrashRemapFd = kMagicChildCrashReportFd;
@ -2251,22 +2304,25 @@ SetRemoteExceptionHandler(const nsACString& crashPipe)
bool
TakeMinidumpForChild(PRUint32 childPid, nsIFile** dump)
TakeMinidumpForChild(PRUint32 childPid, nsIFile** dump, PRUint32* aSequence)
{
if (!GetEnabled())
return false;
MutexAutoLock lock(*dumpMapLock);
nsCOMPtr<nsIFile> d;
bool found = pidToMinidump->Get(childPid, getter_AddRefs(d));
if (found)
pidToMinidump->Remove(childPid);
ChildProcessData* pd = pidToMinidump->GetEntry(childPid);
if (!pd)
return false;
*dump = NULL;
d.swap(*dump);
NS_IF_ADDREF(*dump = pd->minidump);
if (aSequence) {
*aSequence = pd->sequence;
}
pidToMinidump->RemoveEntry(childPid);
return found;
return !!*dump;
}
//-----------------------------------------------------------------------------

View File

@ -69,11 +69,17 @@ nsresult SetSubmitReports(bool aSubmitReport);
// Out-of-process crash reporter API.
// Return true iff a dump was found for |childPid|, and return the
// Initializes out-of-process crash reporting. This method must be called
// before the platform-specifi notificationpipe APIs are called.
void OOPInit();
// Return true if a dump was found for |childPid|, and return the
// path in |dump|. The caller owns the last reference to |dump| if it
// is non-NULL.
// is non-NULL. The sequence parameter will be filled with an ordinal
// indicating which remote process crashed first.
bool TakeMinidumpForChild(PRUint32 childPid,
nsIFile** dump NS_OUTPARAM);
nsIFile** dump NS_OUTPARAM,
PRUint32* aSequence = NULL);
#if defined(XP_WIN)
typedef HANDLE ProcessHandle;
@ -120,9 +126,17 @@ class InjectorCrashCallback
public:
InjectorCrashCallback() { }
virtual void OnCrash(DWORD processID, const nsAString& aDumpID) = 0;
/**
* Inform the callback of a crash. The client code should call
* TakeMinidumpForChild to remove it from the PID mapping table.
*
* The callback will not be fired if the client has already called
* TakeMinidumpForChild for this process ID.
*/
virtual void OnCrash(DWORD processID) = 0;
};
// This method implies OOPInit
void InjectCrashReporterIntoProcess(DWORD processID, InjectorCrashCallback* cb);
void UnregisterInjectorCallback(DWORD processID);
#endif

View File

@ -29,7 +29,7 @@ function run_test()
if (is_windows) {
['SystemMemoryUsePercentage', 'TotalVirtualMemory', 'AvailableVirtualMemory',
'AvailablePageFile', 'AvailablePhysicalMemory'].forEach(function(prop) {
do_check_true(extra[prop].toString().match(/^\d+$/));
do_check_true(/^\d+$/.test(extra[prop].toString()));
});
}
if (is_win7_or_newer)

View File

@ -226,9 +226,10 @@ GeckoProcessType sChildProcessType = GeckoProcessType_Default;
// IPDL wants access to this crashreporter interface, and
// crashreporter is built in such a way to make that awkward
bool
XRE_TakeMinidumpForChild(PRUint32 aChildPid, nsIFile** aDump)
XRE_TakeMinidumpForChild(PRUint32 aChildPid, nsIFile** aDump,
PRUint32* aSequence)
{
return CrashReporter::TakeMinidumpForChild(aChildPid, aDump);
return CrashReporter::TakeMinidumpForChild(aChildPid, aDump, aSequence);
}
bool

View File

@ -367,7 +367,8 @@ XRE_API(GeckoProcessType,
#if defined(MOZ_CRASHREPORTER)
// Used in the "master" parent process hosting the crash server
XRE_API(bool,
XRE_TakeMinidumpForChild, (PRUint32 aChildPid, nsIFile** aDump))
XRE_TakeMinidumpForChild, (PRUint32 aChildPid, nsIFile** aDump,
PRUint32* aSequence))
// Used in child processes.
XRE_API(bool,