2016-10-12 00:25:17 +03:00
|
|
|
/* -*- 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 "CrashReporterHost.h"
|
2018-04-30 22:12:15 +03:00
|
|
|
#include "mozilla/dom/Promise.h"
|
2016-10-12 00:25:17 +03:00
|
|
|
#include "mozilla/Sprintf.h"
|
|
|
|
#include "mozilla/SyncRunnable.h"
|
|
|
|
#include "mozilla/Telemetry.h"
|
2021-04-22 17:32:03 +03:00
|
|
|
#include "nsServiceManagerUtils.h"
|
2017-10-10 13:06:35 +03:00
|
|
|
#include "nsICrashService.h"
|
2019-01-10 18:52:51 +03:00
|
|
|
#include "nsXULAppAPI.h"
|
2021-04-22 17:32:03 +03:00
|
|
|
#include "nsIFile.h"
|
2019-01-10 18:52:51 +03:00
|
|
|
|
2016-10-12 00:25:17 +03:00
|
|
|
namespace mozilla {
|
|
|
|
namespace ipc {
|
|
|
|
|
2017-02-16 01:44:29 +03:00
|
|
|
CrashReporterHost::CrashReporterHost(GeckoProcessType aProcessType,
|
2018-09-17 23:51:45 +03:00
|
|
|
CrashReporter::ThreadId aThreadId)
|
2016-10-12 00:25:17 +03:00
|
|
|
: mProcessType(aProcessType),
|
2017-02-16 01:44:29 +03:00
|
|
|
mThreadId(aThreadId),
|
2017-02-16 01:44:30 +03:00
|
|
|
mStartTime(::time(nullptr)),
|
|
|
|
mFinalized(false) {}
|
2016-10-12 00:25:17 +03:00
|
|
|
|
2017-02-16 01:44:30 +03:00
|
|
|
bool CrashReporterHost::GenerateCrashReport(base::ProcessId aPid) {
|
2024-05-21 22:58:18 +03:00
|
|
|
if (!TakeCrashedChildMinidump(aPid)) {
|
2017-02-16 01:44:30 +03:00
|
|
|
return false;
|
|
|
|
}
|
2022-09-12 22:05:24 +03:00
|
|
|
|
|
|
|
FinalizeCrashReport();
|
|
|
|
RecordCrash(mProcessType, nsICrashService::CRASH_TYPE_CRASH, mDumpID);
|
|
|
|
return true;
|
2017-02-16 01:44:30 +03:00
|
|
|
}
|
|
|
|
|
2017-02-16 01:44:30 +03:00
|
|
|
RefPtr<nsIFile> CrashReporterHost::TakeCrashedChildMinidump(
|
2024-05-21 22:58:18 +03:00
|
|
|
base::ProcessId aPid) {
|
2019-05-18 19:19:55 +03:00
|
|
|
CrashReporter::AnnotationTable annotations;
|
2017-02-16 01:44:30 +03:00
|
|
|
MOZ_ASSERT(!HasMinidump());
|
|
|
|
|
|
|
|
RefPtr<nsIFile> crashDump;
|
2019-05-14 17:06:19 +03:00
|
|
|
if (!CrashReporter::TakeMinidumpForChild(aPid, getter_AddRefs(crashDump),
|
2024-05-21 22:58:18 +03:00
|
|
|
annotations)) {
|
2017-02-16 01:44:30 +03:00
|
|
|
return nullptr;
|
|
|
|
}
|
2019-05-18 19:19:55 +03:00
|
|
|
if (!AdoptMinidump(crashDump, annotations)) {
|
2017-02-16 01:44:30 +03:00
|
|
|
return nullptr;
|
|
|
|
}
|
2019-05-18 19:19:55 +03:00
|
|
|
return crashDump;
|
2017-02-16 01:44:30 +03:00
|
|
|
}
|
|
|
|
|
2019-05-18 19:19:55 +03:00
|
|
|
bool CrashReporterHost::AdoptMinidump(nsIFile* aFile,
|
|
|
|
const AnnotationTable& aAnnotations) {
|
|
|
|
if (!CrashReporter::GetIDFromMinidump(aFile, mDumpID)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
MergeCrashAnnotations(mExtraAnnotations, aAnnotations);
|
|
|
|
return true;
|
2017-02-16 01:44:30 +03:00
|
|
|
}
|
|
|
|
|
2022-09-12 22:05:24 +03:00
|
|
|
void CrashReporterHost::FinalizeCrashReport() {
|
2017-02-16 01:44:30 +03:00
|
|
|
MOZ_ASSERT(!mFinalized);
|
|
|
|
MOZ_ASSERT(HasMinidump());
|
2016-10-12 00:25:17 +03:00
|
|
|
|
2020-04-08 09:55:40 +03:00
|
|
|
mExtraAnnotations[CrashReporter::Annotation::ProcessType] =
|
2019-08-09 17:23:19 +03:00
|
|
|
XRE_ChildProcessTypeToAnnotation(mProcessType);
|
2016-10-12 00:25:17 +03:00
|
|
|
|
|
|
|
char startTime[32];
|
|
|
|
SprintfLiteral(startTime, "%lld", static_cast<long long>(mStartTime));
|
2020-04-08 09:55:40 +03:00
|
|
|
mExtraAnnotations[CrashReporter::Annotation::StartupTime] =
|
Bug 1348273 - Convert crash annotations into a machine-readable list of constants; r=ted.mielczarek,njn,dholbert,mak,cpearce,mcmanus,froydnj,Dexter,jrmuizel,jchen,jimm,bz,surkov
This introduces the machinery needed to generate crash annotations from a YAML
file. The relevant C++ functions are updated to take a typed enum. JavaScript
calls are unaffected but they will throw if the string argument does not
correspond to one of the known entries in the C++ enum. The existing whitelists
and blacklists of annotations are also generated from the YAML file and all
duplicate code related to them has been consolidated. Once written out to the
.extra file the annotations are converted in string form and are no different
than the existing ones.
All existing annotations have been included in the list (and some obsolete ones
have been removed) and all call sites have been updated including tests where
appropriate.
--HG--
extra : source : 4f6c43f2830701ec5552e08e3f1b06fe6d045860
2018-07-05 16:42:11 +03:00
|
|
|
nsDependentCString(startTime);
|
2016-10-12 00:25:17 +03:00
|
|
|
|
2019-05-18 19:19:55 +03:00
|
|
|
CrashReporter::WriteExtraFile(mDumpID, mExtraAnnotations);
|
2022-09-12 12:37:57 +03:00
|
|
|
mFinalized = true;
|
2022-09-12 22:05:24 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void CrashReporterHost::DeleteCrashReport() {
|
|
|
|
if (mFinalized && HasMinidump()) {
|
|
|
|
CrashReporter::DeleteMinidumpFilesForID(mDumpID, Some(u"browser"_ns));
|
|
|
|
}
|
2016-10-12 00:25:17 +03:00
|
|
|
}
|
|
|
|
|
2019-02-26 01:08:36 +03:00
|
|
|
/* static */
|
2019-12-20 20:50:45 +03:00
|
|
|
void CrashReporterHost::RecordCrash(GeckoProcessType aProcessType,
|
|
|
|
int32_t aCrashType,
|
|
|
|
const nsString& aChildDumpID) {
|
2016-10-12 00:25:17 +03:00
|
|
|
if (!NS_IsMainThread()) {
|
2017-06-12 22:34:10 +03:00
|
|
|
RefPtr<Runnable> runnable = NS_NewRunnableFunction(
|
2019-12-20 20:50:45 +03:00
|
|
|
"ipc::CrashReporterHost::RecordCrash", [&]() -> void {
|
|
|
|
CrashReporterHost::RecordCrash(aProcessType, aCrashType,
|
|
|
|
aChildDumpID);
|
2017-06-12 22:34:10 +03:00
|
|
|
});
|
2016-10-12 00:25:17 +03:00
|
|
|
RefPtr<nsIThread> mainThread = do_GetMainThread();
|
|
|
|
SyncRunnable::DispatchToThread(mainThread, runnable);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2019-12-20 20:50:45 +03:00
|
|
|
RecordCrashWithTelemetry(aProcessType, aCrashType);
|
|
|
|
NotifyCrashService(aProcessType, aCrashType, aChildDumpID);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* static */
|
|
|
|
void CrashReporterHost::RecordCrashWithTelemetry(GeckoProcessType aProcessType,
|
|
|
|
int32_t aCrashType) {
|
|
|
|
nsCString key;
|
|
|
|
|
2021-04-06 22:28:20 +03:00
|
|
|
switch (aProcessType) {
|
2021-11-19 17:02:55 +03:00
|
|
|
#define GECKO_PROCESS_TYPE(enum_value, enum_name, string_name, proc_typename, \
|
|
|
|
process_bin_type, procinfo_typename, \
|
|
|
|
webidl_typename, allcaps_name) \
|
|
|
|
case GeckoProcessType_##enum_name: \
|
|
|
|
key.AssignLiteral(string_name); \
|
2019-12-20 20:50:45 +03:00
|
|
|
break;
|
|
|
|
#include "mozilla/GeckoProcessTypes.h"
|
|
|
|
#undef GECKO_PROCESS_TYPE
|
2021-04-06 22:28:20 +03:00
|
|
|
// We can't really hit this, thanks to the above switch, but having it
|
|
|
|
// here will placate the compiler.
|
|
|
|
default:
|
|
|
|
MOZ_ASSERT_UNREACHABLE("unknown process type");
|
2019-12-20 20:50:45 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
Telemetry::Accumulate(Telemetry::SUBPROCESS_CRASHES_WITH_DUMP, key, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* static */
|
|
|
|
void CrashReporterHost::NotifyCrashService(GeckoProcessType aProcessType,
|
|
|
|
int32_t aCrashType,
|
|
|
|
const nsString& aChildDumpID) {
|
2016-10-12 00:25:17 +03:00
|
|
|
MOZ_ASSERT(!aChildDumpID.IsEmpty());
|
|
|
|
|
2017-05-11 15:03:50 +03:00
|
|
|
nsCOMPtr<nsICrashService> crashService =
|
|
|
|
do_GetService("@mozilla.org/crashservice;1");
|
|
|
|
if (!crashService) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2016-10-12 00:25:17 +03:00
|
|
|
int32_t processType;
|
|
|
|
|
|
|
|
switch (aProcessType) {
|
2019-01-10 18:52:51 +03:00
|
|
|
case GeckoProcessType_IPDLUnitTest:
|
|
|
|
case GeckoProcessType_Default:
|
2016-10-12 00:25:17 +03:00
|
|
|
NS_ERROR("unknown process type");
|
|
|
|
return;
|
2019-01-10 18:52:51 +03:00
|
|
|
default:
|
|
|
|
processType = (int)aProcessType;
|
|
|
|
break;
|
2016-10-12 00:25:17 +03:00
|
|
|
}
|
|
|
|
|
2021-04-22 17:32:03 +03:00
|
|
|
RefPtr<dom::Promise> promise;
|
2018-08-14 03:50:11 +03:00
|
|
|
crashService->AddCrash(processType, aCrashType, aChildDumpID,
|
|
|
|
getter_AddRefs(promise));
|
2016-10-12 00:25:17 +03:00
|
|
|
}
|
2017-02-16 01:44:29 +03:00
|
|
|
|
Bug 1831092 - Use the new pull-based API for all crash annotations and remove the global annotations table r=jgilbert,necko-reviewers,media-playback-reviewers,profiler-reviewers,win-reviewers,padenot,handyman,afranchuk,valentin,alwu,sotaro
This changes comes with several different refactorings all rolled into one,
unfotunately I couldn't find a way to pull them apart:
- First of all annotations now can either recorded (that is, we copy the value
and have the crash reporting code own the copy) or registered. Several
annotations are changed to use this functionality so that we don't need to
update them as their value change.
- The code in the exception handler is modified to read the annotations from
the mozannotation_client crate. This has the unfortunate side-effect that
we need three different bits of code to serialize them: one for annotations
read from a child process, one for reading annotations from the main process
outside of the exception handler and one for reading annotations from the
main process within the exception handler. As we move to fully
out-of-process crash reporting the last two methods will go away.
- The mozannotation_client crate now doesn't record annotation types anymore.
I realized as I was working on this that storing types at runtime has two
issues: the first one is that buggy code might change the type of an
annotation (that is record it under two different types at two different
moments), the second issue is that types might become corrupt during a
crash, so better enforce them at annotation-writing time. The end result is
that the mozannotation_* crates now only store byte buffers, track the
format the data is stored in (null-terminated string, fixed size buffer,
etc...) but not the type of data each annotation is supposed to contain.
- Which brings us to the next change: concrete types for annotations are now
enforced when they're written out. If an annotation doesn't match the
expected type it's skipped. Storing an annotation with the wrong type will
also trigger an assertion in debug builds.
Differential Revision: https://phabricator.services.mozilla.com/D195248
2024-03-04 13:24:43 +03:00
|
|
|
void CrashReporterHost::AddAnnotationBool(CrashReporter::Annotation aKey,
|
|
|
|
bool aValue) {
|
|
|
|
MOZ_ASSERT(TypeOfAnnotation(aKey) == CrashReporter::AnnotationType::Boolean,
|
|
|
|
"Wrong annotation type");
|
Bug 1348273 - Convert crash annotations into a machine-readable list of constants; r=ted.mielczarek,njn,dholbert,mak,cpearce,mcmanus,froydnj,Dexter,jrmuizel,jchen,jimm,bz,surkov
This introduces the machinery needed to generate crash annotations from a YAML
file. The relevant C++ functions are updated to take a typed enum. JavaScript
calls are unaffected but they will throw if the string argument does not
correspond to one of the known entries in the C++ enum. The existing whitelists
and blacklists of annotations are also generated from the YAML file and all
duplicate code related to them has been consolidated. Once written out to the
.extra file the annotations are converted in string form and are no different
than the existing ones.
All existing annotations have been included in the list (and some obsolete ones
have been removed) and all call sites have been updated including tests where
appropriate.
--HG--
extra : source : 4f6c43f2830701ec5552e08e3f1b06fe6d045860
2018-07-05 16:42:11 +03:00
|
|
|
mExtraAnnotations[aKey] = aValue ? "1"_ns : "0"_ns;
|
|
|
|
}
|
|
|
|
|
Bug 1831092 - Use the new pull-based API for all crash annotations and remove the global annotations table r=jgilbert,necko-reviewers,media-playback-reviewers,profiler-reviewers,win-reviewers,padenot,handyman,afranchuk,valentin,alwu,sotaro
This changes comes with several different refactorings all rolled into one,
unfotunately I couldn't find a way to pull them apart:
- First of all annotations now can either recorded (that is, we copy the value
and have the crash reporting code own the copy) or registered. Several
annotations are changed to use this functionality so that we don't need to
update them as their value change.
- The code in the exception handler is modified to read the annotations from
the mozannotation_client crate. This has the unfortunate side-effect that
we need three different bits of code to serialize them: one for annotations
read from a child process, one for reading annotations from the main process
outside of the exception handler and one for reading annotations from the
main process within the exception handler. As we move to fully
out-of-process crash reporting the last two methods will go away.
- The mozannotation_client crate now doesn't record annotation types anymore.
I realized as I was working on this that storing types at runtime has two
issues: the first one is that buggy code might change the type of an
annotation (that is record it under two different types at two different
moments), the second issue is that types might become corrupt during a
crash, so better enforce them at annotation-writing time. The end result is
that the mozannotation_* crates now only store byte buffers, track the
format the data is stored in (null-terminated string, fixed size buffer,
etc...) but not the type of data each annotation is supposed to contain.
- Which brings us to the next change: concrete types for annotations are now
enforced when they're written out. If an annotation doesn't match the
expected type it's skipped. Storing an annotation with the wrong type will
also trigger an assertion in debug builds.
Differential Revision: https://phabricator.services.mozilla.com/D195248
2024-03-04 13:24:43 +03:00
|
|
|
void CrashReporterHost::AddAnnotationU32(CrashReporter::Annotation aKey,
|
|
|
|
uint32_t aValue) {
|
|
|
|
MOZ_ASSERT(TypeOfAnnotation(aKey) == CrashReporter::AnnotationType::U32,
|
|
|
|
"Wrong annotation type");
|
Bug 1348273 - Convert crash annotations into a machine-readable list of constants; r=ted.mielczarek,njn,dholbert,mak,cpearce,mcmanus,froydnj,Dexter,jrmuizel,jchen,jimm,bz,surkov
This introduces the machinery needed to generate crash annotations from a YAML
file. The relevant C++ functions are updated to take a typed enum. JavaScript
calls are unaffected but they will throw if the string argument does not
correspond to one of the known entries in the C++ enum. The existing whitelists
and blacklists of annotations are also generated from the YAML file and all
duplicate code related to them has been consolidated. Once written out to the
.extra file the annotations are converted in string form and are no different
than the existing ones.
All existing annotations have been included in the list (and some obsolete ones
have been removed) and all call sites have been updated including tests where
appropriate.
--HG--
extra : source : 4f6c43f2830701ec5552e08e3f1b06fe6d045860
2018-07-05 16:42:11 +03:00
|
|
|
nsAutoCString valueString;
|
|
|
|
valueString.AppendInt(aValue);
|
|
|
|
mExtraAnnotations[aKey] = valueString;
|
|
|
|
}
|
|
|
|
|
Bug 1831092 - Use the new pull-based API for all crash annotations and remove the global annotations table r=jgilbert,necko-reviewers,media-playback-reviewers,profiler-reviewers,win-reviewers,padenot,handyman,afranchuk,valentin,alwu,sotaro
This changes comes with several different refactorings all rolled into one,
unfotunately I couldn't find a way to pull them apart:
- First of all annotations now can either recorded (that is, we copy the value
and have the crash reporting code own the copy) or registered. Several
annotations are changed to use this functionality so that we don't need to
update them as their value change.
- The code in the exception handler is modified to read the annotations from
the mozannotation_client crate. This has the unfortunate side-effect that
we need three different bits of code to serialize them: one for annotations
read from a child process, one for reading annotations from the main process
outside of the exception handler and one for reading annotations from the
main process within the exception handler. As we move to fully
out-of-process crash reporting the last two methods will go away.
- The mozannotation_client crate now doesn't record annotation types anymore.
I realized as I was working on this that storing types at runtime has two
issues: the first one is that buggy code might change the type of an
annotation (that is record it under two different types at two different
moments), the second issue is that types might become corrupt during a
crash, so better enforce them at annotation-writing time. The end result is
that the mozannotation_* crates now only store byte buffers, track the
format the data is stored in (null-terminated string, fixed size buffer,
etc...) but not the type of data each annotation is supposed to contain.
- Which brings us to the next change: concrete types for annotations are now
enforced when they're written out. If an annotation doesn't match the
expected type it's skipped. Storing an annotation with the wrong type will
also trigger an assertion in debug builds.
Differential Revision: https://phabricator.services.mozilla.com/D195248
2024-03-04 13:24:43 +03:00
|
|
|
void CrashReporterHost::AddAnnotationNSCString(CrashReporter::Annotation aKey,
|
|
|
|
const nsACString& aValue) {
|
|
|
|
MOZ_ASSERT(TypeOfAnnotation(aKey) == CrashReporter::AnnotationType::String,
|
|
|
|
"Wrong annotation type");
|
Bug 1348273 - Convert crash annotations into a machine-readable list of constants; r=ted.mielczarek,njn,dholbert,mak,cpearce,mcmanus,froydnj,Dexter,jrmuizel,jchen,jimm,bz,surkov
This introduces the machinery needed to generate crash annotations from a YAML
file. The relevant C++ functions are updated to take a typed enum. JavaScript
calls are unaffected but they will throw if the string argument does not
correspond to one of the known entries in the C++ enum. The existing whitelists
and blacklists of annotations are also generated from the YAML file and all
duplicate code related to them has been consolidated. Once written out to the
.extra file the annotations are converted in string form and are no different
than the existing ones.
All existing annotations have been included in the list (and some obsolete ones
have been removed) and all call sites have been updated including tests where
appropriate.
--HG--
extra : source : 4f6c43f2830701ec5552e08e3f1b06fe6d045860
2018-07-05 16:42:11 +03:00
|
|
|
mExtraAnnotations[aKey] = aValue;
|
2017-02-16 01:44:29 +03:00
|
|
|
}
|
2016-10-12 00:25:17 +03:00
|
|
|
|
|
|
|
} // namespace ipc
|
|
|
|
} // namespace mozilla
|