mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-29 15:52:07 +00:00
Bug 956961 - Open content processes' DMD log files in the parent process. r=njn
This commit is contained in:
parent
e10417743e
commit
adc6a05bd1
@ -59,6 +59,7 @@
|
||||
#include "nsIMutable.h"
|
||||
#include "nsIObserverService.h"
|
||||
#include "nsIScriptSecurityManager.h"
|
||||
#include "nsMemoryInfoDumper.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "nsStyleSheetService.h"
|
||||
#include "nsXULAppAPI.h"
|
||||
@ -192,22 +193,22 @@ public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
MemoryReportRequestChild(uint32_t aGeneration, bool aAnonymize,
|
||||
const nsAString& aDMDDumpIdent);
|
||||
const FileDescriptor& aDMDFile);
|
||||
NS_IMETHOD Run();
|
||||
private:
|
||||
virtual ~MemoryReportRequestChild();
|
||||
|
||||
uint32_t mGeneration;
|
||||
bool mAnonymize;
|
||||
nsString mDMDDumpIdent;
|
||||
FileDescriptor mDMDFile;
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS(MemoryReportRequestChild, nsIRunnable)
|
||||
|
||||
MemoryReportRequestChild::MemoryReportRequestChild(
|
||||
uint32_t aGeneration, bool aAnonymize, const nsAString& aDMDDumpIdent)
|
||||
uint32_t aGeneration, bool aAnonymize, const FileDescriptor& aDMDFile)
|
||||
: mGeneration(aGeneration), mAnonymize(aAnonymize),
|
||||
mDMDDumpIdent(aDMDDumpIdent)
|
||||
mDMDFile(aDMDFile)
|
||||
{
|
||||
MOZ_COUNT_CTOR(MemoryReportRequestChild);
|
||||
}
|
||||
@ -692,10 +693,10 @@ PMemoryReportRequestChild*
|
||||
ContentChild::AllocPMemoryReportRequestChild(const uint32_t& aGeneration,
|
||||
const bool &aAnonymize,
|
||||
const bool &aMinimizeMemoryUsage,
|
||||
const nsString& aDMDDumpIdent)
|
||||
const FileDescriptor& aDMDFile)
|
||||
{
|
||||
MemoryReportRequestChild *actor =
|
||||
new MemoryReportRequestChild(aGeneration, aAnonymize, aDMDDumpIdent);
|
||||
new MemoryReportRequestChild(aGeneration, aAnonymize, aDMDFile);
|
||||
actor->AddRef();
|
||||
return actor;
|
||||
}
|
||||
@ -750,7 +751,7 @@ ContentChild::RecvPMemoryReportRequestConstructor(
|
||||
const uint32_t& aGeneration,
|
||||
const bool& aAnonymize,
|
||||
const bool& aMinimizeMemoryUsage,
|
||||
const nsString& aDMDDumpIdent)
|
||||
const FileDescriptor& aDMDFile)
|
||||
{
|
||||
MemoryReportRequestChild *actor =
|
||||
static_cast<MemoryReportRequestChild*>(aChild);
|
||||
@ -784,7 +785,7 @@ NS_IMETHODIMP MemoryReportRequestChild::Run()
|
||||
new MemoryReportsWrapper(&reports);
|
||||
nsRefPtr<MemoryReportCallback> cb = new MemoryReportCallback(process);
|
||||
mgr->GetReportsForThisProcessExtended(cb, wrappedReports, mAnonymize,
|
||||
mDMDDumpIdent);
|
||||
FileDescriptorToFILE(mDMDFile, "wb"));
|
||||
|
||||
bool sent = Send__delete__(this, mGeneration, reports);
|
||||
return sent ? NS_OK : NS_ERROR_FAILURE;
|
||||
|
@ -155,7 +155,7 @@ public:
|
||||
AllocPMemoryReportRequestChild(const uint32_t& aGeneration,
|
||||
const bool& aAnonymize,
|
||||
const bool& aMinimizeMemoryUsage,
|
||||
const nsString& aDMDDumpIdent) MOZ_OVERRIDE;
|
||||
const FileDescriptor& aDMDFile) MOZ_OVERRIDE;
|
||||
virtual bool
|
||||
DeallocPMemoryReportRequestChild(PMemoryReportRequestChild* actor) MOZ_OVERRIDE;
|
||||
|
||||
@ -164,7 +164,7 @@ public:
|
||||
const uint32_t& aGeneration,
|
||||
const bool& aAnonymize,
|
||||
const bool &aMinimizeMemoryUsage,
|
||||
const nsString &aDMDDumpIdent) MOZ_OVERRIDE;
|
||||
const FileDescriptor &aDMDFile) MOZ_OVERRIDE;
|
||||
|
||||
virtual PCycleCollectWithLogsChild*
|
||||
AllocPCycleCollectWithLogsChild(const bool& aDumpAllTraces,
|
||||
|
@ -103,6 +103,7 @@
|
||||
#include "nsIURIFixup.h"
|
||||
#include "nsIWindowWatcher.h"
|
||||
#include "nsIXULRuntime.h"
|
||||
#include "nsMemoryInfoDumper.h"
|
||||
#include "nsMemoryReporterManager.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "nsStyleSheetService.h"
|
||||
@ -2457,9 +2458,22 @@ ContentParent::Observe(nsISupports* aSubject,
|
||||
// The pre-%n part of the string should be all ASCII, so the byte
|
||||
// offset in identOffset should be correct as a char offset.
|
||||
MOZ_ASSERT(cmsg[identOffset - 1] == '=');
|
||||
FileDescriptor dmdFileDesc;
|
||||
#ifdef MOZ_DMD
|
||||
FILE *dmdFile;
|
||||
nsAutoString dmdIdent(Substring(msg, identOffset));
|
||||
nsresult rv = nsMemoryInfoDumper::OpenDMDFile(dmdIdent, Pid(), &dmdFile);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
// Proceed with the memory report as if DMD were disabled.
|
||||
dmdFile = nullptr;
|
||||
}
|
||||
if (dmdFile) {
|
||||
dmdFileDesc = FILEToFileDescriptor(dmdFile);
|
||||
fclose(dmdFile);
|
||||
}
|
||||
#endif
|
||||
unused << SendPMemoryReportRequestConstructor(
|
||||
generation, anonymize, minimize,
|
||||
nsString(Substring(msg, identOffset)));
|
||||
generation, anonymize, minimize, dmdFileDesc);
|
||||
}
|
||||
}
|
||||
else if (!strcmp(aTopic, "child-gc-request")){
|
||||
@ -2804,7 +2818,7 @@ PMemoryReportRequestParent*
|
||||
ContentParent::AllocPMemoryReportRequestParent(const uint32_t& aGeneration,
|
||||
const bool &aAnonymize,
|
||||
const bool &aMinimizeMemoryUsage,
|
||||
const nsString &aDMDDumpIdent)
|
||||
const FileDescriptor &aDMDFile)
|
||||
{
|
||||
MemoryReportRequestParent* parent = new MemoryReportRequestParent();
|
||||
return parent;
|
||||
|
@ -422,7 +422,7 @@ private:
|
||||
AllocPMemoryReportRequestParent(const uint32_t& aGeneration,
|
||||
const bool &aAnonymize,
|
||||
const bool &aMinimizeMemoryUsage,
|
||||
const nsString &aDMDDumpIdent) MOZ_OVERRIDE;
|
||||
const FileDescriptor &aDMDFile) MOZ_OVERRIDE;
|
||||
virtual bool DeallocPMemoryReportRequestParent(PMemoryReportRequestParent* actor) MOZ_OVERRIDE;
|
||||
|
||||
virtual PCycleCollectWithLogsParent*
|
||||
|
@ -352,7 +352,7 @@ child:
|
||||
async SetProcessSandbox();
|
||||
|
||||
PMemoryReportRequest(uint32_t generation, bool anonymize,
|
||||
bool minimizeMemoryUsage, nsString DMDDumpIdent);
|
||||
bool minimizeMemoryUsage, FileDescriptor DMDFile);
|
||||
|
||||
/**
|
||||
* Notify the AudioChannelService in the child processes.
|
||||
|
@ -47,9 +47,14 @@ nsGZFileWriter::Init(nsIFile* aFile)
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
return InitANSIFileDesc(file);
|
||||
}
|
||||
|
||||
mGZFile = gzdopen(dup(fileno(file)), "wb");
|
||||
fclose(file);
|
||||
NS_IMETHODIMP
|
||||
nsGZFileWriter::InitANSIFileDesc(FILE* aFile)
|
||||
{
|
||||
mGZFile = gzdopen(dup(fileno(aFile)), "wb");
|
||||
fclose(aFile);
|
||||
|
||||
// gzdopen returns nullptr on error.
|
||||
if (NS_WARN_IF(!mGZFile)) {
|
||||
|
@ -8,9 +8,11 @@
|
||||
|
||||
%{C++
|
||||
#include "nsDependentString.h"
|
||||
#include <stdio.h>
|
||||
%}
|
||||
|
||||
interface nsIFile;
|
||||
[ptr] native FILE(FILE);
|
||||
|
||||
/**
|
||||
* A simple interface for writing to a .gz file.
|
||||
@ -22,7 +24,7 @@ interface nsIFile;
|
||||
* The standard gunzip tool cannot decompress a raw gzip stream, but can handle
|
||||
* the files produced by this interface.
|
||||
*/
|
||||
[scriptable, uuid(a256f26a-c603-459e-b5a4-53b4877f2cd8)]
|
||||
[scriptable, uuid(6bd5642c-1b90-4499-ba4b-199f27efaba5)]
|
||||
interface nsIGZFileWriter : nsISupports
|
||||
{
|
||||
/**
|
||||
@ -34,6 +36,12 @@ interface nsIGZFileWriter : nsISupports
|
||||
*/
|
||||
void init(in nsIFile file);
|
||||
|
||||
/**
|
||||
* Alternate version of init() for use when the file is already opened;
|
||||
* e.g., with a FileDescriptor passed over IPC.
|
||||
*/
|
||||
[noscript] void initANSIFileDesc(in FILE file);
|
||||
|
||||
/**
|
||||
* Write the given string to the file.
|
||||
*/
|
||||
|
@ -5,10 +5,14 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsISupports.idl"
|
||||
%{C++
|
||||
#include <stdio.h>
|
||||
%}
|
||||
|
||||
interface nsIDOMWindow;
|
||||
interface nsIRunnable;
|
||||
interface nsISimpleEnumerator;
|
||||
[ptr] native FILE(FILE);
|
||||
|
||||
/*
|
||||
* Memory reporters measure Firefox's memory usage. They are primarily used to
|
||||
@ -201,7 +205,7 @@ interface nsIFinishReportingCallback : nsISupports
|
||||
void callback(in nsISupports data);
|
||||
};
|
||||
|
||||
[scriptable, builtinclass, uuid(c27f8662-a0b7-45b3-8207-14d66b02b9c5)]
|
||||
[scriptable, builtinclass, uuid(51e17609-e98a-47cc-9f95-095ef3c3823e)]
|
||||
interface nsIMemoryReporterManager : nsISupports
|
||||
{
|
||||
/*
|
||||
@ -294,15 +298,14 @@ interface nsIMemoryReporterManager : nsISupports
|
||||
in boolean anonymize);
|
||||
|
||||
/*
|
||||
* As above, but if DMD is enabled and |DMDDumpIdent| is non-empty
|
||||
* then write a DMD report to a file in the usual temporary directory (see
|
||||
* |dumpMemoryInfoToTempDir| in |nsIMemoryInfoDumper|.)
|
||||
* As above, but if DMD is enabled and |DMDFile| is non-null then
|
||||
* write a DMD report to that file and close it.
|
||||
*/
|
||||
[noscript] void
|
||||
getReportsForThisProcessExtended(in nsIMemoryReporterCallback handleReport,
|
||||
in nsISupports handleReportData,
|
||||
in boolean anonymize,
|
||||
in AString DMDDumpIdent);
|
||||
in FILE DMDFile);
|
||||
|
||||
/*
|
||||
* The memory reporter manager, for the most part, treats reporters
|
||||
|
@ -508,12 +508,12 @@ NS_IMPL_ISUPPORTS(DumpReportCallback, nsIHandleReportCallback)
|
||||
|
||||
static void
|
||||
MakeFilename(const char* aPrefix, const nsAString& aIdentifier,
|
||||
const char* aSuffix, nsACString& aResult)
|
||||
int aPid, const char* aSuffix, nsACString& aResult)
|
||||
{
|
||||
aResult = nsPrintfCString("%s-%s-%d.%s",
|
||||
aPrefix,
|
||||
NS_ConvertUTF16toUTF8(aIdentifier).get(),
|
||||
getpid(), aSuffix);
|
||||
aPid, aSuffix);
|
||||
}
|
||||
|
||||
#ifdef MOZ_DMD
|
||||
@ -633,7 +633,8 @@ nsMemoryInfoDumper::DumpMemoryInfoToTempDir(const nsAString& aIdentifier,
|
||||
// each process as was the case before bug 946407. This is so that
|
||||
// the get_about_memory.py script in the B2G repository can
|
||||
// determine when it's done waiting for files to appear.
|
||||
MakeFilename("unified-memory-report", identifier, "json.gz", mrFilename);
|
||||
MakeFilename("unified-memory-report", identifier, getpid(), "json.gz",
|
||||
mrFilename);
|
||||
|
||||
nsCOMPtr<nsIFile> mrTmpFile;
|
||||
nsresult rv;
|
||||
@ -676,24 +677,25 @@ nsMemoryInfoDumper::DumpMemoryInfoToTempDir(const nsAString& aIdentifier,
|
||||
|
||||
#ifdef MOZ_DMD
|
||||
nsresult
|
||||
nsMemoryInfoDumper::DumpDMD(const nsAString& aIdentifier)
|
||||
nsMemoryInfoDumper::OpenDMDFile(const nsAString& aIdentifier, int aPid,
|
||||
FILE** aOutFile)
|
||||
{
|
||||
if (!dmd::IsRunning()) {
|
||||
*aOutFile = nullptr;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult rv;
|
||||
|
||||
// Create a filename like dmd-<identifier>-<pid>.txt.gz, which will be used
|
||||
// if DMD is enabled.
|
||||
nsCString dmdFilename;
|
||||
MakeFilename("dmd", aIdentifier, "txt.gz", dmdFilename);
|
||||
MakeFilename("dmd", aIdentifier, aPid, "txt.gz", dmdFilename);
|
||||
|
||||
// Open a new DMD file named |dmdFilename| in NS_OS_TEMP_DIR for writing,
|
||||
// and dump DMD output to it. This must occur after the memory reporters
|
||||
// have been run (above), but before the memory-reports file has been
|
||||
// renamed (so scripts can detect the DMD file, if present).
|
||||
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIFile> dmdFile;
|
||||
rv = nsDumpUtils::OpenTempFile(dmdFilename,
|
||||
getter_AddRefs(dmdFile),
|
||||
@ -701,15 +703,21 @@ nsMemoryInfoDumper::DumpDMD(const nsAString& aIdentifier)
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
rv = dmdFile->OpenANSIFileDesc("wb", aOutFile);
|
||||
NS_WARN_IF(NS_FAILED(rv));
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsMemoryInfoDumper::DumpDMDToFile(FILE* aFile)
|
||||
{
|
||||
nsRefPtr<nsGZFileWriter> dmdWriter = new nsGZFileWriter();
|
||||
rv = dmdWriter->Init(dmdFile);
|
||||
nsresult rv = dmdWriter->InitANSIFileDesc(aFile);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
// Dump DMD output to the file.
|
||||
|
||||
DMDWriteState state(dmdWriter);
|
||||
dmd::Writer w(DMDWrite, &state);
|
||||
dmd::Dump(w);
|
||||
@ -718,6 +726,21 @@ nsMemoryInfoDumper::DumpDMD(const nsAString& aIdentifier)
|
||||
NS_WARN_IF(NS_FAILED(rv));
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsMemoryInfoDumper::DumpDMD(const nsAString& aIdentifier)
|
||||
{
|
||||
nsresult rv;
|
||||
FILE* dmdFile;
|
||||
rv = OpenDMDFile(aIdentifier, getpid(), &dmdFile);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
if (!dmdFile) {
|
||||
return NS_OK;
|
||||
}
|
||||
return DumpDMDToFile(dmdFile);
|
||||
}
|
||||
#endif // MOZ_DMD
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -8,6 +8,7 @@
|
||||
#define mozilla_nsMemoryInfoDumper_h
|
||||
|
||||
#include "nsIMemoryInfoDumper.h"
|
||||
#include <stdio.h>
|
||||
|
||||
class nsACString;
|
||||
|
||||
@ -31,7 +32,14 @@ public:
|
||||
static void Initialize();
|
||||
|
||||
#ifdef MOZ_DMD
|
||||
// Write a DMD report.
|
||||
static nsresult DumpDMD(const nsAString& aIdentifier);
|
||||
// Open an appropriately named file for a DMD report. If DMD is
|
||||
// disabled, return a null FILE* instead.
|
||||
static nsresult OpenDMDFile(const nsAString& aIdentifier, int aPid,
|
||||
FILE** aOutFile);
|
||||
// Write a DMD report to the given file and close it.
|
||||
static nsresult DumpDMDToFile(FILE* aFile);
|
||||
#endif
|
||||
};
|
||||
|
||||
|
@ -1104,8 +1104,17 @@ nsMemoryReporterManager::StartGettingReports()
|
||||
GetReportsState* s = mGetReportsState;
|
||||
|
||||
// Get reports for this process.
|
||||
FILE *parentDMDFile = nullptr;
|
||||
#ifdef MOZ_DMD
|
||||
nsresult rv = nsMemoryInfoDumper::OpenDMDFile(s->mDMDDumpIdent, getpid(),
|
||||
&parentDMDFile);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
// Proceed with the memory report as if DMD were disabled.
|
||||
parentDMDFile = nullptr;
|
||||
}
|
||||
#endif
|
||||
GetReportsForThisProcessExtended(s->mHandleReport, s->mHandleReportData,
|
||||
s->mAnonymize, s->mDMDDumpIdent);
|
||||
s->mAnonymize, parentDMDFile);
|
||||
s->mParentDone = true;
|
||||
|
||||
// If there are no remaining child processes, we can finish up immediately.
|
||||
@ -1138,13 +1147,13 @@ nsMemoryReporterManager::GetReportsForThisProcess(
|
||||
nsISupports* aHandleReportData, bool aAnonymize)
|
||||
{
|
||||
return GetReportsForThisProcessExtended(aHandleReport, aHandleReportData,
|
||||
aAnonymize, nsString());
|
||||
aAnonymize, nullptr);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemoryReporterManager::GetReportsForThisProcessExtended(
|
||||
nsIHandleReportCallback* aHandleReport, nsISupports* aHandleReportData,
|
||||
bool aAnonymize, const nsAString& aDMDDumpIdent)
|
||||
bool aAnonymize, FILE* aDMDFile)
|
||||
{
|
||||
// Memory reporters are not necessarily threadsafe, so this function must
|
||||
// be called from the main thread.
|
||||
@ -1153,11 +1162,13 @@ nsMemoryReporterManager::GetReportsForThisProcessExtended(
|
||||
}
|
||||
|
||||
#ifdef MOZ_DMD
|
||||
if (!aDMDDumpIdent.IsEmpty()) {
|
||||
if (aDMDFile) {
|
||||
// Clear DMD's reportedness state before running the memory
|
||||
// reporters, to avoid spurious twice-reported warnings.
|
||||
dmd::ClearReports();
|
||||
}
|
||||
#else
|
||||
MOZ_ASSERT(!aDMDFile);
|
||||
#endif
|
||||
|
||||
MemoryReporterArray allReporters;
|
||||
@ -1172,8 +1183,8 @@ nsMemoryReporterManager::GetReportsForThisProcessExtended(
|
||||
}
|
||||
|
||||
#ifdef MOZ_DMD
|
||||
if (!aDMDDumpIdent.IsEmpty()) {
|
||||
return nsMemoryInfoDumper::DumpDMD(aDMDDumpIdent);
|
||||
if (aDMDFile) {
|
||||
return nsMemoryInfoDumper::DumpDMDToFile(aDMDFile);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user