Backed out 2 changesets (bug 1614933) for bc failures at browser_tabicon_after_bg_tab_crash.js.

Backed out changeset 59503d3a702f (bug 1614933)
Backed out changeset 578c8ba9598f (bug 1614933)
This commit is contained in:
Brindusan Cristian 2020-03-22 17:30:07 +02:00
Родитель 14d6560dd3
Коммит 4646c1f41f
27 изменённых файлов: 517 добавлений и 97 удалений

Просмотреть файл

@ -3455,9 +3455,9 @@ void ContentParent::FriendlyName(nsAString& aName, bool aAnonymize) {
}
mozilla::ipc::IPCResult ContentParent::RecvInitCrashReporter(
const NativeThreadId& aThreadId) {
mCrashReporter =
MakeUnique<CrashReporterHost>(GeckoProcessType_Content, aThreadId);
Shmem&& aShmem, const NativeThreadId& aThreadId) {
mCrashReporter = MakeUnique<CrashReporterHost>(GeckoProcessType_Content,
aShmem, aThreadId);
return IPC_OK();
}

Просмотреть файл

@ -429,7 +429,7 @@ class ContentParent final
virtual void OnChannelError() override;
mozilla::ipc::IPCResult RecvInitCrashReporter(
const NativeThreadId& aThreadId);
Shmem&& aShmem, const NativeThreadId& aThreadId);
PNeckoParent* AllocPNeckoParent();

Просмотреть файл

@ -889,7 +889,7 @@ parent:
async PRemoteSpellcheckEngine();
async InitCrashReporter(NativeThreadId tid);
async InitCrashReporter(Shmem shmem, NativeThreadId tid);
sync IsSecureURI(uint32_t aType, URIParams aURI, uint32_t aFlags,
OriginAttributes aOriginAttributes)

Просмотреть файл

@ -18,7 +18,7 @@ intr protocol PGMP
manages PGMPStorage;
parent:
async InitCrashReporter(NativeThreadId threadId);
async InitCrashReporter(Shmem shmem, NativeThreadId threadId);
async PGMPTimer();
async PGMPStorage();

Просмотреть файл

@ -49,7 +49,7 @@ parent:
child:
async InitCrashReporter(NativeThreadId threadId);
async InitCrashReporter(Shmem shmem, NativeThreadId threadId);
async AddMemoryReport(MemoryReport aReport);
async FinishMemoryReport(uint32_t aGeneration);

Просмотреть файл

@ -88,7 +88,7 @@ child:
async SetParentHangTimeout(uint32_t seconds);
intr InitCrashReporter()
intr InitCrashReporter(Shmem shmem)
returns (NativeThreadId tid);
async SettingChanged(PluginSettings settings);

Просмотреть файл

@ -715,8 +715,8 @@ mozilla::ipc::IPCResult PluginModuleChild::RecvInitPluginFunctionBroker(
}
mozilla::ipc::IPCResult PluginModuleChild::AnswerInitCrashReporter(
mozilla::dom::NativeThreadId* aOutId) {
CrashReporterClient::InitSingleton();
Shmem&& aShmem, mozilla::dom::NativeThreadId* aOutId) {
CrashReporterClient::InitSingletonWithShmem(aShmem);
*aOutId = CrashReporter::CurrentThreadId();
return IPC_OK();

Просмотреть файл

@ -97,7 +97,7 @@ class PluginModuleChild : public PPluginModuleChild {
mozilla::ipc::IPCResult RecvSetParentHangTimeout(const uint32_t& aSeconds);
mozilla::ipc::IPCResult AnswerInitCrashReporter(
mozilla::dom::NativeThreadId* aId);
Shmem&& aShmem, mozilla::dom::NativeThreadId* aId);
virtual void ActorDestroy(ActorDestroyReason why) override;

Просмотреть файл

@ -527,15 +527,20 @@ void PluginModuleChromeParent::OnProcessLaunched(const bool aSucceeded) {
}
bool PluginModuleChromeParent::InitCrashReporter() {
ipc::Shmem shmem;
if (!ipc::CrashReporterClient::AllocShmem(this, &shmem)) {
return false;
}
NativeThreadId threadId;
if (!CallInitCrashReporter(&threadId)) {
if (!CallInitCrashReporter(std::move(shmem), &threadId)) {
return false;
}
{
mozilla::MutexAutoLock lock(mCrashReporterMutex);
mCrashReporter =
MakeUnique<ipc::CrashReporterHost>(GeckoProcessType_Plugin, threadId);
mCrashReporter = MakeUnique<ipc::CrashReporterHost>(GeckoProcessType_Plugin,
shmem, threadId);
}
return true;

Просмотреть файл

@ -120,7 +120,7 @@ child:
// Graphics errors, analogous to PContent::GraphicsError
async GraphicsError(nsCString aError);
async InitCrashReporter(NativeThreadId threadId);
async InitCrashReporter(Shmem shmem, NativeThreadId threadId);
async CreateVRProcess();
async ShutdownVRProcess();

Просмотреть файл

@ -39,7 +39,7 @@ child:
async InitComplete();
async OpenVRControllerActionPathToParent(nsCString aPath);
async OpenVRControllerManifestPathToParent(VRControllerType aType, nsCString aPath);
async InitCrashReporter(NativeThreadId threadId);
async InitCrashReporter(Shmem shmem, NativeThreadId threadId);
async AddMemoryReport(MemoryReport aReport);
async FinishMemoryReport(uint32_t aGeneration);
};

Просмотреть файл

@ -5,6 +5,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "CrashReporterClient.h"
#include "CrashReporterMetadataShmem.h"
#include "nsISupportsImpl.h"
namespace mozilla {
@ -13,7 +14,8 @@ namespace ipc {
StaticMutex CrashReporterClient::sLock;
StaticRefPtr<CrashReporterClient> CrashReporterClient::sClientSingleton;
CrashReporterClient::CrashReporterClient() {
CrashReporterClient::CrashReporterClient(const Shmem& aShmem)
: mMetadata(new CrashReporterMetadataShmem(aShmem)) {
MOZ_COUNT_CTOR(CrashReporterClient);
}
@ -21,14 +23,27 @@ CrashReporterClient::~CrashReporterClient() {
MOZ_COUNT_DTOR(CrashReporterClient);
}
void CrashReporterClient::AnnotateCrashReport(CrashReporter::Annotation aKey,
const nsACString& aData) {
StaticMutexAutoLock lock(sLock);
mMetadata->AnnotateCrashReport(aKey, aData);
}
void CrashReporterClient::AppendAppNotes(const nsACString& aData) {
StaticMutexAutoLock lock(sLock);
mMetadata->AppendAppNotes(aData);
}
/* static */
void CrashReporterClient::InitSingleton() {
void CrashReporterClient::InitSingletonWithShmem(const Shmem& aShmem) {
{
StaticMutexAutoLock lock(sLock);
MOZ_ASSERT(!sClientSingleton);
sClientSingleton = new CrashReporterClient();
sClientSingleton = new CrashReporterClient(aShmem);
}
CrashReporter::NotifyCrashReporterClientCreated();
}
/* static */

Просмотреть файл

@ -11,36 +11,66 @@
#include "mozilla/StaticMutex.h"
#include "mozilla/StaticPtr.h"
#include "mozilla/Unused.h"
#include "mozilla/ipc/Shmem.h"
namespace mozilla {
namespace ipc {
class CrashReporterMetadataShmem;
class CrashReporterClient {
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(CrashReporterClient);
// |aTopLevelProtocol| must have a child-to-parent message:
// |aTopLevelProtocol| must be a top-level protocol instance, as sub-actors
// do not have AllocUnsafeShmem. It must also have a child-to-parent message:
//
// async InitCrashReporter(NativeThreadId threadId);
// async InitCrashReporter(Shmem shmem, NativeThreadId threadId);
//
// The parent-side receive function of this message should save the shmem
// somewhere, and when the top-level actor's ActorDestroy runs (or when the
// crash reporter needs metadata), the shmem should be parsed.
template <typename T>
static void InitSingleton(T* aToplevelProtocol) {
InitSingleton();
Shmem shmem;
if (!AllocShmem(aToplevelProtocol, &shmem)) {
MOZ_DIAGNOSTIC_ASSERT(false, "failed to allocate crash reporter shmem");
return;
}
InitSingletonWithShmem(shmem);
Unused << aToplevelProtocol->SendInitCrashReporter(
CrashReporter::CurrentThreadId());
std::move(shmem), CrashReporter::CurrentThreadId());
}
static void InitSingleton();
template <typename T>
static bool AllocShmem(T* aToplevelProtocol, Shmem* aOutShmem) {
// 16KB should be enough for most metadata - see bug 1278717 comment #11.
static const size_t kShmemSize = 16 * 1024;
return aToplevelProtocol->AllocUnsafeShmem(
kShmemSize, SharedMemory::TYPE_BASIC, aOutShmem);
}
static void InitSingletonWithShmem(const Shmem& aShmem);
static void DestroySingleton();
static RefPtr<CrashReporterClient> GetSingleton();
void AnnotateCrashReport(CrashReporter::Annotation aKey,
const nsACString& aData);
void AppendAppNotes(const nsACString& aData);
private:
explicit CrashReporterClient();
explicit CrashReporterClient(const Shmem& aShmem);
~CrashReporterClient();
private:
static StaticMutex sLock;
static StaticRefPtr<CrashReporterClient> sClientSingleton;
private:
UniquePtr<CrashReporterMetadataShmem> mMetadata;
};
} // namespace ipc

Просмотреть файл

@ -6,6 +6,7 @@
#define mozilla_ipc_CrashReporterHelper_h
#include "CrashReporterHost.h"
#include "mozilla/ipc/Shmem.h"
#include "mozilla/UniquePtr.h"
#include "nsExceptionHandler.h"
#include "nsICrashService.h"
@ -18,7 +19,7 @@ namespace ipc {
* toplevel protocols representing processes. To use this class, you should:
*
* 1. Declare a method to initialize the crash reporter in your IPDL:
* `async InitCrashReporter(NativeThreadId threadId)`
* `async InitCrashReporter(Shmem shmem, NativeThreadId threadId)`
*
* 2. Inherit from this class, providing the appropriate `GeckoProcessType`
* enum value for the template parameter PT.
@ -32,8 +33,9 @@ template <GeckoProcessType PT>
class CrashReporterHelper {
public:
CrashReporterHelper() : mCrashReporter(nullptr) {}
IPCResult RecvInitCrashReporter(const CrashReporter::ThreadId& aThreadId) {
mCrashReporter = MakeUnique<ipc::CrashReporterHost>(PT, aThreadId);
IPCResult RecvInitCrashReporter(Shmem&& aShmem,
const CrashReporter::ThreadId& aThreadId) {
mCrashReporter = MakeUnique<ipc::CrashReporterHost>(PT, aShmem, aThreadId);
return IPC_OK();
}

Просмотреть файл

@ -5,6 +5,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "CrashReporterHost.h"
#include "CrashReporterMetadataShmem.h"
#include "mozilla/dom/Promise.h"
#include "mozilla/Sprintf.h"
#include "mozilla/SyncRunnable.h"
@ -57,8 +58,10 @@ namespace mozilla {
namespace ipc {
CrashReporterHost::CrashReporterHost(GeckoProcessType aProcessType,
const Shmem& aShmem,
CrashReporter::ThreadId aThreadId)
: mProcessType(aProcessType),
mShmem(aShmem),
mThreadId(aThreadId),
mStartTime(::time(nullptr)),
mFinalized(false) {}
@ -109,14 +112,22 @@ bool CrashReporterHost::FinalizeCrashReport() {
MOZ_ASSERT(!mFinalized);
MOZ_ASSERT(HasMinidump());
mExtraAnnotations[CrashReporter::Annotation::ProcessType] =
CrashReporter::AnnotationTable annotations;
annotations[CrashReporter::Annotation::ProcessType] =
XRE_ChildProcessTypeToAnnotation(mProcessType);
char startTime[32];
SprintfLiteral(startTime, "%lld", static_cast<long long>(mStartTime));
mExtraAnnotations[CrashReporter::Annotation::StartupTime] =
annotations[CrashReporter::Annotation::StartupTime] =
nsDependentCString(startTime);
// We might not have shmem (for example, when running crashreporter tests).
if (mShmem.IsReadable()) {
CrashReporterMetadataShmem::ReadAppNotes(mShmem, annotations);
}
MergeCrashAnnotations(mExtraAnnotations, annotations);
CrashReporter::WriteExtraFile(mDumpID, mExtraAnnotations);
RecordCrash(mProcessType, GetCrashType(), mDumpID);

Просмотреть файл

@ -10,6 +10,7 @@
#include <functional>
#include "mozilla/UniquePtr.h"
#include "mozilla/ipc/Shmem.h"
#include "base/process.h"
#include "nsExceptionHandler.h"
#include "nsThreadUtils.h"
@ -19,14 +20,16 @@ namespace mozilla {
namespace ipc {
// This is the newer replacement for CrashReporterParent. It is created in
// response to a InitCrashReporter message on a top-level actor. When the
// process terminates abnormally, the top-level should call GenerateCrashReport
// to automatically integrate metadata.
// response to a InitCrashReporter message on a top-level actor, and simply
// holds the metadata shmem alive until the process ends. When the process
// terminates abnormally, the top-level should call GenerateCrashReport to
// automatically integrate metadata.
class CrashReporterHost {
typedef mozilla::ipc::Shmem Shmem;
typedef CrashReporter::AnnotationTable AnnotationTable;
public:
CrashReporterHost(GeckoProcessType aProcessType,
CrashReporterHost(GeckoProcessType aProcessType, const Shmem& aShmem,
CrashReporter::ThreadId aThreadId);
// Helper function for generating a crash report for a process that probably
@ -118,6 +121,7 @@ class CrashReporterHost {
private:
GeckoProcessType mProcessType;
Shmem mShmem;
CrashReporter::ThreadId mThreadId;
time_t mStartTime;
AnnotationTable mExtraAnnotations;

Просмотреть файл

@ -0,0 +1,225 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* 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/. */
#include "CrashReporterMetadataShmem.h"
#include "mozilla/Attributes.h"
#include "mozilla/EnumeratedRange.h"
#include "nsISupportsImpl.h"
namespace mozilla {
namespace ipc {
using CrashReporter::Annotation;
enum class EntryType : uint8_t {
None,
Annotation,
};
CrashReporterMetadataShmem::CrashReporterMetadataShmem(const Shmem& aShmem)
: mShmem(aShmem) {
MOZ_COUNT_CTOR(CrashReporterMetadataShmem);
}
CrashReporterMetadataShmem::~CrashReporterMetadataShmem() {
MOZ_COUNT_DTOR(CrashReporterMetadataShmem);
}
void CrashReporterMetadataShmem::AnnotateCrashReport(Annotation aKey,
const nsACString& aData) {
mAnnotations[aKey] = aData;
SyncNotesToShmem();
}
void CrashReporterMetadataShmem::AppendAppNotes(const nsACString& aData) {
mAppNotes.Append(aData);
mAnnotations[Annotation::Notes] = mAppNotes;
SyncNotesToShmem();
}
class MOZ_STACK_CLASS MetadataShmemWriter {
public:
explicit MetadataShmemWriter(const Shmem& aShmem)
: mCursor(aShmem.get<uint8_t>()), mEnd(mCursor + aShmem.Size<uint8_t>()) {
*mCursor = uint8_t(EntryType::None);
}
MOZ_MUST_USE bool WriteAnnotation(Annotation aKey, const nsCString& aValue) {
// This shouldn't happen because Commit() guarantees mCursor < mEnd. But
// we might as well be safe.
if (mCursor >= mEnd) {
return false;
}
// Save the current position so we can write the entry type if the entire
// entry fits.
uint8_t* start = mCursor++;
if (!Write(aKey) || !Write(aValue)) {
return false;
}
return Commit(start, EntryType::Annotation);
}
private:
// On success, append a new terminal byte. On failure, rollback the cursor.
MOZ_MUST_USE bool Commit(uint8_t* aStart, EntryType aType) {
MOZ_ASSERT(aStart < mEnd);
MOZ_ASSERT(EntryType(*aStart) == EntryType::None);
if (mCursor >= mEnd) {
// No room for a terminating byte - rollback.
mCursor = aStart;
return false;
}
// Commit the entry and write a new terminal byte.
*aStart = uint8_t(aType);
*mCursor = uint8_t(EntryType::None);
return true;
}
MOZ_MUST_USE bool Write(const nsCString& aString) {
// 32-bit length is okay since our shmems are very small (16K),
// a huge write would fail anyway.
return Write(static_cast<uint32_t>(aString.Length())) &&
Write(aString.get(), aString.Length());
}
template <typename T>
MOZ_MUST_USE bool Write(const T& aT) {
return Write(&aT, sizeof(T));
}
MOZ_MUST_USE bool Write(const void* aData, size_t aLength) {
if (size_t(mEnd - mCursor) < aLength) {
return false;
}
memcpy(mCursor, aData, aLength);
mCursor += aLength;
return true;
}
private:
// The cursor (beginning at start) always points to a single byte
// representing the next EntryType. An EntryType is either None,
// indicating there are no more entries, or Annotation, meaning
// two strings follow.
//
// Strings are written as a 32-bit length and byte sequence. After each new
// entry, a None entry is always appended, and a subsequent entry will
// overwrite this byte.
uint8_t* mCursor;
uint8_t* mEnd;
};
void CrashReporterMetadataShmem::SyncNotesToShmem() {
MetadataShmemWriter writer(mShmem);
for (auto key : MakeEnumeratedRange(Annotation::Count)) {
if (!mAnnotations[key].IsEmpty()) {
if (!writer.WriteAnnotation(key, mAnnotations[key])) {
return;
}
}
}
}
// Helper class to iterate over metadata entries encoded in shmem.
class MOZ_STACK_CLASS MetadataShmemReader {
public:
explicit MetadataShmemReader(const Shmem& aShmem)
: mEntryType(EntryType::None) {
mCursor = aShmem.get<uint8_t>();
mEnd = mCursor + aShmem.Size<uint8_t>();
// Advance to the first item, if any.
Next();
}
bool Done() const { return mCursor >= mEnd || Type() == EntryType::None; }
EntryType Type() const { return mEntryType; }
void Next() {
if (mCursor < mEnd) {
mEntryType = EntryType(*mCursor++);
} else {
mEntryType = EntryType::None;
}
}
template <typename T>
bool Read(T* aOut) {
return Read(aOut, sizeof(T));
}
bool Read(nsCString& aOut) {
uint32_t length = 0;
if (!Read(&length)) {
return false;
}
const uint8_t* src = Read(length);
if (!src) {
return false;
}
aOut.Assign((const char*)src, length);
return true;
}
private:
bool Read(void* aOut, size_t aLength) {
const uint8_t* src = Read(aLength);
if (!src) {
return false;
}
memcpy(aOut, src, aLength);
return true;
}
// If buffer has |aLength| bytes, return cursor and then advance it.
// Otherwise, return null.
const uint8_t* Read(size_t aLength) {
if (size_t(mEnd - mCursor) < aLength) {
return nullptr;
}
const uint8_t* result = mCursor;
mCursor += aLength;
return result;
}
private:
const uint8_t* mCursor;
const uint8_t* mEnd;
EntryType mEntryType;
};
void CrashReporterMetadataShmem::ReadAppNotes(const Shmem& aShmem,
AnnotationTable& aNotes) {
for (MetadataShmemReader reader(aShmem); !reader.Done(); reader.Next()) {
switch (reader.Type()) {
case EntryType::Annotation: {
Annotation key;
nsCString value;
if (!reader.Read(&key) || !reader.Read(value)) {
return;
}
if (key >= Annotation::Count) {
return;
}
aNotes[key] = value;
break;
}
default:
NS_ASSERTION(false, "Unknown metadata entry type");
break;
}
}
}
} // namespace ipc
} // namespace mozilla

Просмотреть файл

@ -0,0 +1,47 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* 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/. */
#ifndef mozilla_ipc_CrashReporterMetadataShmem_h
#define mozilla_ipc_CrashReporterMetadataShmem_h
#include <stdint.h>
#include "mozilla/ipc/Shmem.h"
#include "nsExceptionHandler.h"
#include "nsString.h"
namespace mozilla {
namespace ipc {
class CrashReporterMetadataShmem {
typedef mozilla::ipc::Shmem Shmem;
typedef CrashReporter::AnnotationTable AnnotationTable;
public:
explicit CrashReporterMetadataShmem(const Shmem& aShmem);
~CrashReporterMetadataShmem();
// Metadata writers. These must only be called in child processes.
void AnnotateCrashReport(CrashReporter::Annotation aKey,
const nsACString& aData);
void AppendAppNotes(const nsACString& aData);
static void ReadAppNotes(const Shmem& aShmem,
CrashReporter::AnnotationTable& aNotes);
private:
void SyncNotesToShmem();
private:
Shmem mShmem;
AnnotationTable mAnnotations;
nsCString mAppNotes;
};
} // namespace ipc
} // namespace mozilla
#endif // mozilla_ipc_CrashReporterMetadataShmem_h

Просмотреть файл

@ -6,7 +6,6 @@
#include "mozilla/ipc/IdleSchedulerChild.h"
#include "mozilla/ipc/IdleSchedulerParent.h"
#include "mozilla/ipc/PBackgroundChild.h"
#include "mozilla/Atomics.h"
#include "mozilla/IdlePeriodState.h"
#include "BackgroundChild.h"

Просмотреть файл

@ -19,6 +19,7 @@ EXPORTS.mozilla.ipc += [
'CrashReporterClient.h',
'CrashReporterHelper.h',
'CrashReporterHost.h',
'CrashReporterMetadataShmem.h',
'CrossProcessMutex.h',
'CrossProcessSemaphore.h',
'EnvironmentMap.h',
@ -151,6 +152,7 @@ UNIFIED_SOURCES += [
'BrowserProcessSubThread.cpp',
'CrashReporterClient.cpp',
'CrashReporterHost.cpp',
'CrashReporterMetadataShmem.cpp',
'FileDescriptor.cpp',
'FileDescriptorUtils.cpp',
'IdleSchedulerChild.cpp',

Просмотреть файл

@ -50,7 +50,7 @@ protocol PSocketProcess
manages PAltSvcTransaction;
parent:
async InitCrashReporter(NativeThreadId threadId);
async InitCrashReporter(Shmem shmem, NativeThreadId threadId);
async AddMemoryReport(MemoryReport aReport);
async FinishMemoryReport(uint32_t aGeneration);
// Messages for sending telemetry to parent process.

Просмотреть файл

@ -19,6 +19,10 @@ class MemoryReport;
class MemoryReportRequestHost;
} // namespace dom
namespace ipc {
class CrashReporterHost;
} // namespace ipc
namespace net {
class SocketProcessHost;

Просмотреть файл

@ -27,7 +27,6 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/prctl.h>
#include <sys/ptrace.h>
#include <sys/syscall.h>
@ -501,14 +500,6 @@ void SandboxEarlyInit() {
}
}
static void RunGlibcLazyInitializers() {
// Make glibc's lazy initialization of shm_open() run before sandboxing
int fd = shm_open("/dummy", O_RDONLY, 0);
if (fd > 0) {
close(fd); // In the unlikely case we actually opened something
}
}
static void SandboxLateInit() {
#ifdef NIGHTLY_BUILD
gSandboxCrashOnError = true;
@ -525,8 +516,6 @@ static void SandboxLateInit() {
gSandboxCrashOnError = envVar[0] != '0';
}
}
RunGlibcLazyInitializers();
}
// Common code for sandbox startup.

Просмотреть файл

@ -26,7 +26,7 @@ struct LaunchParameters {
intr protocol PRemoteSandboxBroker
{
parent:
async InitCrashReporter(NativeThreadId threadId);
async InitCrashReporter(Shmem shmem, NativeThreadId threadId);
child:
intr LaunchApp(LaunchParameters params)
returns (bool ok, uint64_t handle);

Просмотреть файл

@ -39,6 +39,8 @@ nsresult SetupExtraData(nsIFile* aAppDataDirectory,
nsresult UnsetExceptionHandler() { return NS_ERROR_NOT_IMPLEMENTED; }
void NotifyCrashReporterClientCreated() {}
nsresult AnnotateCrashReport(Annotation key, bool data) {
return NS_ERROR_NOT_IMPLEMENTED;
}

Просмотреть файл

@ -24,6 +24,7 @@
#include "mozilla/StaticMutex.h"
#include "mozilla/SyncRunnable.h"
#include "mozilla/TimeStamp.h"
#include "mozilla/ipc/CrashReporterClient.h"
#include "nsThreadUtils.h"
#include "nsThread.h"
@ -121,6 +122,7 @@ using google_breakpad::kDefaultBuildIdSize;
using google_breakpad::PageAllocator;
#endif
using namespace mozilla;
using mozilla::ipc::CrashReporterClient;
namespace CrashReporter {
@ -310,6 +312,11 @@ class ReportInjectedCrash : public Runnable {
};
#endif // MOZ_CRASHREPORTER_INJECTOR
// If annotations are attempted before the crash reporter is enabled,
// they queue up here.
class DelayedNote;
nsTArray<UniquePtr<DelayedNote> >* gDelayedAnnotations;
#if defined(XP_WIN)
// the following are used to prevent other DLLs reverting the last chance
// exception handler to the windows default. Any attempt to change the
@ -1296,21 +1303,16 @@ static void WriteMozCrashReason(AnnotationWriter& aWriter) {
}
}
static void WriteAnnotations(AnnotationWriter& writer,
const AnnotationTable& aAnnotations) {
for (auto key : MakeEnumeratedRange(Annotation::Count)) {
const nsCString& value = aAnnotations[key];
if (!value.IsEmpty()) {
writer.Write(key, value.get(), value.Length());
}
}
}
static void WriteAnnotationsForMainProcessCrash(PlatformWriter& pw,
const phc::AddrInfo* addrInfo,
time_t crashTime) {
JSONAnnotationWriter writer(pw);
WriteAnnotations(writer, crashReporterAPIData_Table);
for (auto key : MakeEnumeratedRange(Annotation::Count)) {
const nsCString& value = crashReporterAPIData_Table[key];
if (!value.IsEmpty()) {
writer.Write(key, value.get(), value.Length());
}
}
char crashTimeString[32];
XP_TTOA(crashTime, crashTimeString);
@ -1675,8 +1677,6 @@ static void PrepareChildExceptionTimeAnnotations(
}
};
GetFlatThreadAnnotation(getThreadAnnotationCB, true);
WriteAnnotations(writer, crashReporterAPIData_Table);
}
#ifdef XP_WIN
@ -1830,29 +1830,6 @@ static nsresult LocateExecutable(nsIFile* aXREDirectory,
#endif // !defined(MOZ_WIDGET_ANDROID)
static void InitializeAnnotationFacilities() {
crashReporterAPILock = new Mutex("crashReporterAPILock");
notesFieldLock = new Mutex("notesFieldLock");
notesField = new nsCString();
InitThreadAnnotation();
}
static void TeardownAnnotationFacilities() {
std::fill(crashReporterAPIData_Table.begin(),
crashReporterAPIData_Table.end(), EmptyCString());
delete crashReporterAPILock;
crashReporterAPILock = nullptr;
delete notesFieldLock;
notesFieldLock = nullptr;
delete notesField;
notesField = nullptr;
ShutdownThreadAnnotation();
}
nsresult SetExceptionHandler(nsIFile* aXREDirectory, bool force /*=false*/) {
if (gExceptionHandler) return NS_ERROR_ALREADY_INITIALIZED;
@ -1872,7 +1849,13 @@ nsresult SetExceptionHandler(nsIFile* aXREDirectory, bool force /*=false*/) {
// the crash reporter client
doReport = ShouldReport();
InitializeAnnotationFacilities();
NS_ASSERTION(!crashReporterAPILock, "Shouldn't have a lock yet");
crashReporterAPILock = new Mutex("crashReporterAPILock");
NS_ASSERTION(!notesFieldLock, "Shouldn't have a lock yet");
notesFieldLock = new Mutex("notesFieldLock");
notesField = new nsCString();
NS_ENSURE_TRUE(notesField, NS_ERROR_OUT_OF_MEMORY);
#if !defined(MOZ_WIDGET_ANDROID)
// Locate the crash reporter executable
@ -2052,6 +2035,8 @@ nsresult SetExceptionHandler(nsIFile* aXREDirectory, bool force /*=false*/) {
oldTerminateHandler = std::set_terminate(&TerminateHandler);
InitThreadAnnotation();
return NS_OK;
}
@ -2297,7 +2282,19 @@ nsresult UnsetExceptionHandler() {
delete gExceptionHandler;
TeardownAnnotationFacilities();
// do this here in the unlikely case that we succeeded in allocating
// our strings but failed to allocate gExceptionHandler.
std::fill(crashReporterAPIData_Table.begin(),
crashReporterAPIData_Table.end(), EmptyCString());
delete crashReporterAPILock;
crashReporterAPILock = nullptr;
delete notesFieldLock;
notesFieldLock = nullptr;
delete notesField;
notesField = nullptr;
if (pendingDirectory) {
free(pendingDirectory);
@ -2326,6 +2323,8 @@ nsresult UnsetExceptionHandler() {
memoryReportPath = nullptr;
}
ShutdownThreadAnnotation();
if (!gExceptionHandler) return NS_ERROR_NOT_INITIALIZED;
gExceptionHandler = nullptr;
@ -2340,6 +2339,45 @@ nsresult UnsetExceptionHandler() {
return NS_OK;
}
class DelayedNote {
public:
DelayedNote(Annotation aKey, const nsACString& aData)
: mKey(aKey), mData(aData), mType(CrashAnnotation) {}
explicit DelayedNote(const nsACString& aData)
: mData(aData), mType(AppNote) {}
void Run() {
if (mType == CrashAnnotation) {
AnnotateCrashReport(mKey, mData);
} else {
AppendAppNotesToCrashReport(mData);
}
}
private:
Annotation mKey;
nsCString mData;
enum AnnotationType { CrashAnnotation, AppNote } mType;
};
static void EnqueueDelayedNote(DelayedNote* aNote) {
if (!gDelayedAnnotations) {
gDelayedAnnotations = new nsTArray<UniquePtr<DelayedNote> >();
}
gDelayedAnnotations->AppendElement(WrapUnique(aNote));
}
void NotifyCrashReporterClientCreated() {
if (gDelayedAnnotations) {
for (const auto& note : *gDelayedAnnotations) {
note->Run();
}
delete gDelayedAnnotations;
gDelayedAnnotations = nullptr;
}
}
nsresult AnnotateCrashReport(Annotation key, bool data) {
return AnnotateCrashReport(
key, data ? NS_LITERAL_CSTRING("1") : NS_LITERAL_CSTRING("0"));
@ -2362,6 +2400,21 @@ nsresult AnnotateCrashReport(Annotation key, unsigned int data) {
nsresult AnnotateCrashReport(Annotation key, const nsACString& data) {
if (!GetEnabled()) return NS_ERROR_NOT_INITIALIZED;
if (!XRE_IsParentProcess()) {
// The newer CrashReporterClient can be used from any thread.
if (RefPtr<CrashReporterClient> client =
CrashReporterClient::GetSingleton()) {
client->AnnotateCrashReport(key, data);
return NS_OK;
}
// EnqueueDelayedNote() can only be called on the main thread.
MOZ_RELEASE_ASSERT(NS_IsMainThread());
EnqueueDelayedNote(new DelayedNote(key, data));
return NS_OK;
}
MutexAutoLock lock(*crashReporterAPILock);
crashReporterAPIData_Table[key] = data;
@ -2383,10 +2436,10 @@ void MergeCrashAnnotations(AnnotationTable& aDst, const AnnotationTable& aSrc) {
}
}
static void MergeContentCrashAnnotations(AnnotationTable& aDst) {
MutexAutoLock lock(*crashReporterAPILock);
static void MergeContentCrashAnnotations(AnnotationTable& aDst,
const AnnotationTable& aSrc) {
for (auto key : MakeEnumeratedRange(Annotation::Count)) {
const nsCString& value = crashReporterAPIData_Table[key];
const nsCString& value = aSrc[key];
if (value.IsEmpty() || IsAnnotationBlacklistedForContent(key)) {
continue;
}
@ -2432,6 +2485,20 @@ void SetMinidumpAnalysisAllThreads() {
nsresult AppendAppNotesToCrashReport(const nsACString& data) {
if (!GetEnabled()) return NS_ERROR_NOT_INITIALIZED;
if (!XRE_IsParentProcess()) {
if (RefPtr<CrashReporterClient> client =
CrashReporterClient::GetSingleton()) {
client->AppendAppNotes(data);
return NS_OK;
}
// EnqueueDelayedNote can only be called on the main thread.
MOZ_RELEASE_ASSERT(NS_IsMainThread());
EnqueueDelayedNote(new DelayedNote(data));
return NS_OK;
}
MutexAutoLock lock(*notesFieldLock);
notesField->Append(data);
@ -3089,7 +3156,12 @@ static bool WriteExtraFile(PlatformWriter pw,
}
JSONAnnotationWriter writer(pw);
WriteAnnotations(writer, aAnnotations);
for (auto key : MakeEnumeratedRange(Annotation::Count)) {
const nsCString& value = aAnnotations[key];
if (!value.IsEmpty()) {
writer.Write(key, value.get(), value.Length());
}
}
return true;
}
@ -3119,14 +3191,19 @@ static void ReadExceptionTimeAnnotations(AnnotationTable& aAnnotations,
if (aPid && processToCrashFd.count(aPid)) {
PRFileDesc* prFd = processToCrashFd[aPid];
processToCrashFd.erase(aPid);
ReadAndValidateExceptionTimeAnnotations(prFd, aAnnotations);
AnnotationTable exceptionTimeAnnotations;
ReadAndValidateExceptionTimeAnnotations(prFd, exceptionTimeAnnotations);
MergeCrashAnnotations(aAnnotations, exceptionTimeAnnotations);
PR_Close(prFd);
}
}
static void PopulateContentProcessAnnotations(AnnotationTable& aAnnotations,
uint32_t aPid) {
MergeContentCrashAnnotations(aAnnotations);
{
MutexAutoLock lock(*crashReporterAPILock);
MergeContentCrashAnnotations(aAnnotations, crashReporterAPIData_Table);
}
AddCommonAnnotations(aAnnotations);
ReadExceptionTimeAnnotations(aAnnotations, aPid);
}
@ -3435,8 +3512,6 @@ bool SetRemoteExceptionHandler(const char* aCrashPipe,
uintptr_t aCrashTimeAnnotationFile) {
MOZ_ASSERT(!gExceptionHandler, "crash client already init'd");
InitializeAnnotationFacilities();
#if defined(XP_WIN)
gExceptionHandler = new google_breakpad::ExceptionHandler(
L"", ChildFPEFilter,
@ -3472,6 +3547,8 @@ bool SetRemoteExceptionHandler(const char* aCrashPipe,
oldTerminateHandler = std::set_terminate(&TerminateHandler);
InitThreadAnnotation();
// we either do remote or nothing, no fallback to regular crash reporting
return gExceptionHandler->IsOutOfProcess();
}
@ -3745,7 +3822,12 @@ bool CreateMinidumpsAndPair(ProcessHandle aTargetPid,
DllBlocklist_Shutdown();
#endif
MergeContentCrashAnnotations(aTargetAnnotations);
{
MutexAutoLock lock(*crashReporterAPILock);
MergeContentCrashAnnotations(aTargetAnnotations,
crashReporterAPIData_Table);
}
AddCommonAnnotations(aTargetAnnotations);
targetMinidump.forget(aMainDumpOut);
@ -3799,8 +3881,7 @@ bool UnsetRemoteExceptionHandler() {
delete gExceptionHandler;
gExceptionHandler = nullptr;
#endif
TeardownAnnotationFacilities();
ShutdownThreadAnnotation();
return true;
}

Просмотреть файл

@ -97,6 +97,10 @@ nsresult AnnotateCrashReport(Annotation key, const nsACString& data);
nsresult RemoveCrashReportAnnotation(Annotation key);
nsresult AppendAppNotesToCrashReport(const nsACString& data);
// Called after the crash reporter client has been created in a content
// process, allowing annotations to be processed.
void NotifyCrashReporterClientCreated();
void AnnotateOOMAllocationSize(size_t size);
void AnnotateTexturesSize(size_t size);
nsresult SetGarbageCollecting(bool collecting);