зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1776694 - Make GrabShutdownProfile return the additional information as well r=mstange
Depends on D170502 Differential Revision: https://phabricator.services.mozilla.com/D170783
This commit is contained in:
Родитель
1f69fa0f99
Коммит
a4cea1aea6
|
@ -3075,7 +3075,7 @@ void ContentChild::ShutdownInternal() {
|
|||
CrashReporter::Annotation::ProfilerChildShutdownPhase,
|
||||
isProfiling ? "Profiling - GrabShutdownProfileAndShutdown"_ns
|
||||
: "Not profiling - GrabShutdownProfileAndShutdown"_ns);
|
||||
nsCString shutdownProfile =
|
||||
ProfileAndAdditionalInformation shutdownProfileAndAdditionalInformation =
|
||||
mProfilerController->GrabShutdownProfileAndShutdown();
|
||||
CrashReporter::AnnotateCrashReport(
|
||||
CrashReporter::Annotation::ProfilerChildShutdownPhase,
|
||||
|
@ -3086,16 +3086,17 @@ void ContentChild::ShutdownInternal() {
|
|||
CrashReporter::Annotation::ProfilerChildShutdownPhase,
|
||||
isProfiling ? "Profiling - SendShutdownProfile (sending)"_ns
|
||||
: "Not profiling - SendShutdownProfile (sending)"_ns);
|
||||
if (const size_t len = shutdownProfile.Length();
|
||||
if (const size_t len = shutdownProfileAndAdditionalInformation.SizeOf();
|
||||
len >= size_t(IPC::Channel::kMaximumMessageSize)) {
|
||||
shutdownProfile = nsPrintfCString(
|
||||
shutdownProfileAndAdditionalInformation.mProfile = nsPrintfCString(
|
||||
"*Profile from pid %u bigger (%zu) than IPC max (%zu)",
|
||||
unsigned(profiler_current_process_id().ToNumber()), len,
|
||||
size_t(IPC::Channel::kMaximumMessageSize));
|
||||
}
|
||||
// Send the shutdown profile to the parent process through our own
|
||||
// message channel, which we know will survive for long enough.
|
||||
bool sent = SendShutdownProfile(shutdownProfile);
|
||||
bool sent =
|
||||
SendShutdownProfile(shutdownProfileAndAdditionalInformation.mProfile);
|
||||
CrashReporter::AnnotateCrashReport(
|
||||
CrashReporter::Annotation::ProfilerChildShutdownPhase,
|
||||
sent ? (isProfiling ? "Profiling - SendShutdownProfile (sent)"_ns
|
||||
|
|
|
@ -53,10 +53,11 @@ void ChildProfilerController::Init(Endpoint<PProfilerChild>&& aEndpoint) {
|
|||
}
|
||||
}
|
||||
|
||||
nsCString ChildProfilerController::GrabShutdownProfileAndShutdown() {
|
||||
nsCString shutdownProfile;
|
||||
ShutdownAndMaybeGrabShutdownProfileFirst(&shutdownProfile);
|
||||
return shutdownProfile;
|
||||
ProfileAndAdditionalInformation
|
||||
ChildProfilerController::GrabShutdownProfileAndShutdown() {
|
||||
ProfileAndAdditionalInformation profileAndAdditionalInformation;
|
||||
ShutdownAndMaybeGrabShutdownProfileFirst(&profileAndAdditionalInformation);
|
||||
return profileAndAdditionalInformation;
|
||||
}
|
||||
|
||||
void ChildProfilerController::Shutdown() {
|
||||
|
@ -64,7 +65,7 @@ void ChildProfilerController::Shutdown() {
|
|||
}
|
||||
|
||||
void ChildProfilerController::ShutdownAndMaybeGrabShutdownProfileFirst(
|
||||
nsCString* aOutShutdownProfile) {
|
||||
ProfileAndAdditionalInformation* aOutShutdownProfileInformation) {
|
||||
// First, get the owning reference out of mThread, so it cannot be used in
|
||||
// ChildProfilerController after this (including re-entrantly during the
|
||||
// profilerChildThread->Shutdown() inner event loop below).
|
||||
|
@ -80,10 +81,10 @@ void ChildProfilerController::ShutdownAndMaybeGrabShutdownProfileFirst(
|
|||
CrashReporter::Annotation::ProfilerChildShutdownPhase,
|
||||
"Profiling - Dispatching ShutdownProfilerChild"_ns);
|
||||
profilerChildThread->Dispatch(
|
||||
NewRunnableMethod<nsCString*>(
|
||||
NewRunnableMethod<ProfileAndAdditionalInformation*>(
|
||||
"ChildProfilerController::ShutdownProfilerChild", this,
|
||||
&ChildProfilerController::ShutdownProfilerChild,
|
||||
aOutShutdownProfile),
|
||||
aOutShutdownProfileInformation),
|
||||
NS_DISPATCH_NORMAL);
|
||||
// Shut down the thread. This call will spin until all runnables
|
||||
// (including the ShutdownProfilerChild runnable) have been processed.
|
||||
|
@ -96,7 +97,7 @@ void ChildProfilerController::ShutdownAndMaybeGrabShutdownProfileFirst(
|
|||
// done synchronously. This avoids having to manually shutdown the thread,
|
||||
// which runs a risky inner event loop, see bug 1613798.
|
||||
profilerChildThread->Dispatch(
|
||||
NewRunnableMethod<nsCString*>(
|
||||
NewRunnableMethod<ProfileAndAdditionalInformation*>(
|
||||
"ChildProfilerController::ShutdownProfilerChild SYNC", this,
|
||||
&ChildProfilerController::ShutdownProfilerChild, nullptr),
|
||||
NS_DISPATCH_SYNC);
|
||||
|
@ -143,14 +144,14 @@ void ChildProfilerController::SetupProfilerChild(
|
|||
}
|
||||
|
||||
void ChildProfilerController::ShutdownProfilerChild(
|
||||
nsCString* aOutShutdownProfile) {
|
||||
ProfileAndAdditionalInformation* aOutShutdownProfileInformation) {
|
||||
const bool isProfiling = profiler_is_active();
|
||||
if (aOutShutdownProfile) {
|
||||
if (aOutShutdownProfileInformation) {
|
||||
CrashReporter::AnnotateCrashReport(
|
||||
CrashReporter::Annotation::ProfilerChildShutdownPhase,
|
||||
isProfiling ? "Profiling - GrabShutdownProfile"_ns
|
||||
: "Not profiling - GrabShutdownProfile"_ns);
|
||||
*aOutShutdownProfile = mProfilerChild->GrabShutdownProfile();
|
||||
*aOutShutdownProfileInformation = mProfilerChild->GrabShutdownProfile();
|
||||
}
|
||||
CrashReporter::AnnotateCrashReport(
|
||||
CrashReporter::Annotation::ProfilerChildShutdownPhase,
|
||||
|
|
|
@ -485,7 +485,7 @@ void ProfilerChild::Destroy() {
|
|||
}
|
||||
}
|
||||
|
||||
nsCString ProfilerChild::GrabShutdownProfile() {
|
||||
ProfileAndAdditionalInformation ProfilerChild::GrabShutdownProfile() {
|
||||
LOG("GrabShutdownProfile");
|
||||
|
||||
UniquePtr<ProfilerCodeAddressService> service =
|
||||
|
@ -498,32 +498,36 @@ nsCString ProfilerChild::GrabShutdownProfile() {
|
|||
/* aIsShuttingDown */ true, service.get(), ProgressLogger{});
|
||||
if (rv.isErr()) {
|
||||
const char* failure = writer.GetFailure();
|
||||
return nsPrintfCString("*Profile unavailable for pid %u%s%s",
|
||||
unsigned(profiler_current_process_id().ToNumber()),
|
||||
failure ? ", failure: " : "",
|
||||
failure ? failure : "");
|
||||
return ProfileAndAdditionalInformation(
|
||||
nsPrintfCString("*Profile unavailable for pid %u%s%s",
|
||||
unsigned(profiler_current_process_id().ToNumber()),
|
||||
failure ? ", failure: " : "", failure ? failure : ""));
|
||||
}
|
||||
|
||||
auto additionalInfo = rv.unwrap();
|
||||
|
||||
writer.StartArrayProperty("processes");
|
||||
writer.EndArray();
|
||||
writer.End();
|
||||
|
||||
const size_t len = writer.ChunkedWriteFunc().Length();
|
||||
// This string is destined to be sent as a shutdown profile, which is limited
|
||||
// by the maximum IPC message size.
|
||||
// This string and information are destined to be sent as a shutdown profile,
|
||||
// which is limited by the maximum IPC message size.
|
||||
// TODO: IPC to change to shmem (bug 1780330), raising this limit to
|
||||
// JS::MaxStringLength.
|
||||
if (len >= size_t(IPC::Channel::kMaximumMessageSize)) {
|
||||
return nsPrintfCString(
|
||||
"*Profile from pid %u bigger (%zu) than IPC max (%zu)",
|
||||
unsigned(profiler_current_process_id().ToNumber()), len,
|
||||
size_t(IPC::Channel::kMaximumMessageSize));
|
||||
if (len + additionalInfo.SizeOf() >=
|
||||
size_t(IPC::Channel::kMaximumMessageSize)) {
|
||||
return ProfileAndAdditionalInformation(
|
||||
nsPrintfCString("*Profile from pid %u bigger (%zu) than IPC max (%zu)",
|
||||
unsigned(profiler_current_process_id().ToNumber()), len,
|
||||
size_t(IPC::Channel::kMaximumMessageSize)));
|
||||
}
|
||||
|
||||
nsCString profileCString;
|
||||
if (!profileCString.SetLength(len, fallible)) {
|
||||
return nsPrintfCString(
|
||||
return ProfileAndAdditionalInformation(nsPrintfCString(
|
||||
"*Could not allocate %zu bytes for profile from pid %u", len,
|
||||
unsigned(profiler_current_process_id().ToNumber()));
|
||||
unsigned(profiler_current_process_id().ToNumber())));
|
||||
}
|
||||
MOZ_ASSERT(*(profileCString.Data() + len) == '\0',
|
||||
"We expected a null at the end of the string buffer, to be "
|
||||
|
@ -531,8 +535,9 @@ nsCString ProfilerChild::GrabShutdownProfile() {
|
|||
|
||||
char* const profileBeginWriting = profileCString.BeginWriting();
|
||||
if (!profileBeginWriting) {
|
||||
return nsPrintfCString("*Could not write profile from pid %u",
|
||||
unsigned(profiler_current_process_id().ToNumber()));
|
||||
return ProfileAndAdditionalInformation(
|
||||
nsPrintfCString("*Could not write profile from pid %u",
|
||||
unsigned(profiler_current_process_id().ToNumber())));
|
||||
}
|
||||
|
||||
// Here, we have enough space reserved in `profileCString`, starting at
|
||||
|
@ -542,13 +547,15 @@ nsCString ProfilerChild::GrabShutdownProfile() {
|
|||
MOZ_RELEASE_ASSERT(aBufferLen == len + 1);
|
||||
return profileBeginWriting;
|
||||
})) {
|
||||
return nsPrintfCString("*Could not copy profile from pid %u",
|
||||
unsigned(profiler_current_process_id().ToNumber()));
|
||||
return ProfileAndAdditionalInformation(
|
||||
nsPrintfCString("*Could not copy profile from pid %u",
|
||||
unsigned(profiler_current_process_id().ToNumber())));
|
||||
}
|
||||
MOZ_ASSERT(*(profileCString.Data() + len) == '\0',
|
||||
"We still expected a null at the end of the string buffer");
|
||||
|
||||
return profileCString;
|
||||
return ProfileAndAdditionalInformation{std::move(profileCString),
|
||||
std::move(additionalInfo)};
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include "mozilla/RefPtr.h"
|
||||
#include "nsISupportsImpl.h"
|
||||
#include "nsStringFwd.h"
|
||||
#include "ProfileAdditionalInformation.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
|
@ -31,18 +32,21 @@ class ChildProfilerController final {
|
|||
static already_AddRefed<ChildProfilerController> Create(
|
||||
mozilla::ipc::Endpoint<PProfilerChild>&& aEndpoint);
|
||||
|
||||
[[nodiscard]] nsCString GrabShutdownProfileAndShutdown();
|
||||
[[nodiscard]] ProfileAndAdditionalInformation
|
||||
GrabShutdownProfileAndShutdown();
|
||||
void Shutdown();
|
||||
|
||||
private:
|
||||
ChildProfilerController();
|
||||
~ChildProfilerController();
|
||||
void Init(mozilla::ipc::Endpoint<PProfilerChild>&& aEndpoint);
|
||||
void ShutdownAndMaybeGrabShutdownProfileFirst(nsCString* aOutShutdownProfile);
|
||||
void ShutdownAndMaybeGrabShutdownProfileFirst(
|
||||
ProfileAndAdditionalInformation* aOutShutdownProfileInformation);
|
||||
|
||||
// Called on mThread:
|
||||
void SetupProfilerChild(mozilla::ipc::Endpoint<PProfilerChild>&& aEndpoint);
|
||||
void ShutdownProfilerChild(nsCString* aOutShutdownProfile);
|
||||
void ShutdownProfilerChild(
|
||||
ProfileAndAdditionalInformation* aOutShutdownProfileInformation);
|
||||
|
||||
RefPtr<ProfilerChild> mProfilerChild; // only accessed on mThread
|
||||
DataMutex<RefPtr<nsIThread>> mThread;
|
||||
|
|
|
@ -381,7 +381,7 @@ mozilla::UniquePtr<char[]> profiler_get_profile(double aSinceTime = 0,
|
|||
|
||||
// Write the profile for this process (excluding subprocesses) into aWriter.
|
||||
// Returns a failed result if the profiler is inactive.
|
||||
ProfilerResult<ProfileGenerationAdditionalInformation>
|
||||
ProfilerResult<mozilla::ProfileGenerationAdditionalInformation>
|
||||
profiler_stream_json_for_this_process(
|
||||
mozilla::baseprofiler::SpliceableJSONWriter& aWriter, double aSinceTime = 0,
|
||||
bool aIsShuttingDown = false,
|
||||
|
|
|
@ -16,10 +16,36 @@
|
|||
|
||||
#include "shared-libraries.h"
|
||||
|
||||
namespace mozilla {
|
||||
// This structure contains additional information gathered while generating the
|
||||
// profile json and iterating the buffer.
|
||||
struct ProfileGenerationAdditionalInformation {
|
||||
SharedLibraryInfo sharedLibraries;
|
||||
size_t SizeOf() const { return mSharedLibraries.SizeOf(); }
|
||||
SharedLibraryInfo mSharedLibraries;
|
||||
};
|
||||
|
||||
#endif
|
||||
struct ProfileAndAdditionalInformation {
|
||||
ProfileAndAdditionalInformation() = default;
|
||||
explicit ProfileAndAdditionalInformation(const nsCString&& aProfile)
|
||||
: mProfile(aProfile) {}
|
||||
|
||||
ProfileAndAdditionalInformation(
|
||||
const nsCString&& aProfile,
|
||||
const ProfileGenerationAdditionalInformation&& aAdditionalInformation)
|
||||
: mProfile(aProfile),
|
||||
mAdditionalInformation(Some(aAdditionalInformation)) {}
|
||||
|
||||
size_t SizeOf() const {
|
||||
size_t size = mProfile.Length();
|
||||
if (mAdditionalInformation.isSome()) {
|
||||
size += mAdditionalInformation->SizeOf();
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
nsCString mProfile;
|
||||
Maybe<ProfileGenerationAdditionalInformation> mAdditionalInformation;
|
||||
};
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // ProfileAdditionalInformation_h
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include "mozilla/ProfileBufferControlledChunkManager.h"
|
||||
#include "mozilla/ProgressLogger.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "ProfileAdditionalInformation.h"
|
||||
|
||||
class nsIThread;
|
||||
struct PRThread;
|
||||
|
@ -33,7 +34,7 @@ class ProfilerChild final : public PProfilerChild,
|
|||
// This method can be used to grab a profile just before PProfiler is torn
|
||||
// down. The collected profile should then be sent through a different
|
||||
// message channel that is guaranteed to stay open long enough.
|
||||
nsCString GrabShutdownProfile();
|
||||
ProfileAndAdditionalInformation GrabShutdownProfile();
|
||||
|
||||
void Destroy();
|
||||
|
||||
|
|
|
@ -68,6 +68,12 @@ class SharedLibrary {
|
|||
const nsString& GetDebugPath() const { return mDebugPath; }
|
||||
const nsCString& GetVersion() const { return mVersion; }
|
||||
const std::string& GetArch() const { return mArch; }
|
||||
size_t SizeOf() const {
|
||||
return sizeof *this + mBreakpadId.Length() + mCodeId.Length() +
|
||||
mModuleName.Length() * 2 + mModulePath.Length() * 2 +
|
||||
mDebugName.Length() * 2 + mDebugPath.Length() * 2 +
|
||||
mVersion.Length() + mArch.size();
|
||||
}
|
||||
|
||||
private:
|
||||
SharedLibrary() : mStart{0}, mEnd{0}, mOffset{0} {}
|
||||
|
@ -130,6 +136,16 @@ class SharedLibraryInfo {
|
|||
|
||||
void Clear() { mEntries.clear(); }
|
||||
|
||||
size_t SizeOf() const {
|
||||
size_t size = 0;
|
||||
|
||||
for (const auto& item : mEntries) {
|
||||
size += item.SizeOf();
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<SharedLibrary> mEntries;
|
||||
};
|
||||
|
|
Загрузка…
Ссылка в новой задаче