diff --git a/ipc/docs/processes.rst b/ipc/docs/processes.rst index 8e0a84059712..e2db59ed2966 100644 --- a/ipc/docs/processes.rst +++ b/ipc/docs/processes.rst @@ -130,6 +130,11 @@ Crash reporting - Add new ``Xxx*Status`` `annotations `_ entry for your new process type description. The link here points to `UtilityProcessStatus` so you can see the similar description you have to write, but you might want to respect ordering in that file and put your new code at the appropriate place. - Add entry in `PROCESS_CRASH_SUBMIT_ATTEMPT `_ +Memory reporting +################# + +- Add handling for your new process within `nsMemoryReporterManager::GetReportsExtended ` + Process reporting ################# diff --git a/ipc/glue/test/browser/browser.ini b/ipc/glue/test/browser/browser.ini index 82638583b8c4..745105704b8e 100644 --- a/ipc/glue/test/browser/browser.ini +++ b/ipc/glue/test/browser/browser.ini @@ -2,6 +2,7 @@ support-files = ../../../../tools/profiler/tests/shared-head.js +[browser_utility_memoryReport.js] [browser_utility_profiler.js] skip-if = tsan # from tools/profiler/tests/browser/browser.ini, timing out on profiler tests? [browser_utility_start.js] diff --git a/ipc/glue/test/browser/browser_utility_memoryReport.js b/ipc/glue/test/browser/browser_utility_memoryReport.js new file mode 100644 index 000000000000..8aa9ae22b142 --- /dev/null +++ b/ipc/glue/test/browser/browser_utility_memoryReport.js @@ -0,0 +1,80 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +var utilityPid = undefined; +var utilityReports = []; + +add_task(async () => { + const utilityProcessTest = Cc[ + "@mozilla.org/utility-process-test;1" + ].createInstance(Ci.nsIUtilityProcessTest); + await utilityProcessTest + .startProcess() + .then(async pid => { + utilityPid = pid; + ok(true, "Could start Utility process: " + pid); + }) + .catch(async () => { + ok(false, "Cannot start Utility process?"); + }); +}); + +add_task(async () => { + const gMgr = Cc["@mozilla.org/memory-reporter-manager;1"].getService( + Ci.nsIMemoryReporterManager + ); + ok(utilityPid !== undefined, "Utility process is running"); + + const performCollection = new Promise((resolve, reject) => { + // Record the reports from the live memory reporters then process them. + let handleReport = function( + aProcess, + aUnsafePath, + aKind, + aUnits, + aAmount, + aDescription + ) { + const expectedProcess = `Utility (pid ${utilityPid})`; + if (aProcess !== expectedProcess) { + return; + } + + let report = { + process: aProcess, + path: aUnsafePath, + kind: aKind, + units: aUnits, + amount: aAmount, + description: aDescription, + }; + + utilityReports.push(report); + }; + + info("Memory report: Perform the call"); + gMgr.getReports(handleReport, null, resolve, null, false); + }); + + await performCollection; + + info("Collected", utilityReports.length, "reports from utility process"); + ok(!!utilityReports.length, "Collected some reports"); + ok( + utilityReports.filter(r => r.path === "vsize" && r.amount > 0).length === 1, + "Collected vsize report" + ); + ok( + utilityReports.filter(r => r.path === "resident" && r.amount > 0).length === + 1, + "Collected resident report" + ); + ok( + !!utilityReports.filter( + r => r.path.search(/^explicit\/.*/) >= 0 && r.amount > 0 + ).length, + "Collected some explicit/ report" + ); +}); diff --git a/xpcom/base/nsMemoryReporterManager.cpp b/xpcom/base/nsMemoryReporterManager.cpp index bd4629c7858f..cef33434c149 100644 --- a/xpcom/base/nsMemoryReporterManager.cpp +++ b/xpcom/base/nsMemoryReporterManager.cpp @@ -40,6 +40,7 @@ #include "mozilla/dom/MemoryReportTypes.h" #include "mozilla/dom/ContentParent.h" #include "mozilla/gfx/GPUProcessManager.h" +#include "mozilla/ipc/UtilityProcessManager.h" #include "mozilla/ipc/FileDescriptorUtils.h" #ifdef XP_WIN @@ -54,6 +55,7 @@ #endif using namespace mozilla; +using namespace mozilla::ipc; using namespace dom; #if defined(MOZ_MEMORY) @@ -1808,6 +1810,14 @@ nsresult nsMemoryReporterManager::StartGettingReports() { } } + if (RefPtr utility = + UtilityProcessManager::GetSingleton()) { + if (RefPtr proc = + utility->GetProcessMemoryReporter()) { + s->mChildrenPending.AppendElement(proc.forget()); + } + } + if (!s->mChildrenPending.IsEmpty()) { nsCOMPtr timer; rv = NS_NewTimerWithFuncCallback(