1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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_ProcInfo_h
#define __mozilla_ProcInfo_h
#include <base/process.h>
#include <stdint.h>
#include "mozilla/dom/BindingDeclarations.h"
#include "mozilla/dom/ChromeUtilsBinding.h"
#include "mozilla/dom/ipc/IdType.h"
#include "mozilla/HashTable.h"
#include "mozilla/MozPromise.h"
namespace mozilla {
namespace ipc {
class GeckoChildProcessHost;
}
/**
* Return the number of milliseconds of CPU time used since process start.
*
* @return NS_OK on success.
*/
nsresult GetCpuTimeSinceProcessStartInMs(uint64_t* aResult);
/**
* Return the number of milliseconds of GPU time used since process start.
*
* @return NS_OK on success.
*/
nsresult GetGpuTimeSinceProcessStartInMs(uint64_t* aResult);
// Process types. When updating this enum, please make sure to update
// WebIDLProcType, ChromeUtils::RequestProcInfo and ProcTypeToWebIDL to
// mirror the changes.
enum class ProcType {
// These must match the ones in RemoteType.h, and E10SUtils.sys.mjs
Web,
WebIsolated,
File,
Extension,
PrivilegedAbout,
PrivilegedMozilla,
WebCOOPCOEP,
WebServiceWorker,
// the rest matches GeckoProcessTypes.h
#define GECKO_PROCESS_TYPE(enum_value, enum_name, string_name, proc_typename, \
process_bin_type, procinfo_typename, \
webidl_typename, allcaps_name) \
procinfo_typename,
#define SKIP_PROCESS_TYPE_CONTENT
#ifndef MOZ_ENABLE_FORKSERVER
# define SKIP_PROCESS_TYPE_FORKSERVER
#endif // MOZ_ENABLE_FORKSERVER
#include "mozilla/GeckoProcessTypes.h"
#undef SKIP_PROCESS_TYPE_CONTENT
#ifndef MOZ_ENABLE_FORKSERVER
# undef SKIP_PROCESS_TYPE_FORKSERVER
#endif // MOZ_ENABLE_FORKSERVER
#undef GECKO_PROCESS_TYPE
Preallocated,
// Unknown type of process
Unknown,
Max = Unknown,
};
using UtilityActorName = mozilla::dom::WebIDLUtilityActorName;
// String that will be used e.g. to annotate crash reports
nsCString GetUtilityActorName(const UtilityActorName aActorName);
#ifdef XP_WIN
int GetCpuFrequencyMHz();
#endif
/* Get the CPU frequency to use to convert cycle time values to actual time.
* @returns the TSC (Time Stamp Counter) frequency in MHz, or 0 if converting
* cycle time values should not be attempted. */
int GetCycleTimeFrequencyMHz();
struct ThreadInfo {
// Thread Id.
base::ProcessId tid = 0;
// Thread name, if any.
nsString name;
// CPU time in ns.
uint64_t cpuTime = 0;
// CPU time in cycles if available.
uint64_t cpuCycleCount = 0;
};
// Info on a DOM window.
struct WindowInfo {
explicit WindowInfo()
: outerWindowId(0),
documentURI(nullptr),
documentTitle(u""_ns),
isProcessRoot(false),
isInProcess(false) {}
WindowInfo(uint64_t aOuterWindowId, nsIURI* aDocumentURI,
nsAString&& aDocumentTitle, bool aIsProcessRoot, bool aIsInProcess)
: outerWindowId(aOuterWindowId),
documentURI(aDocumentURI),
documentTitle(std::move(aDocumentTitle)),
isProcessRoot(aIsProcessRoot),
isInProcess(aIsInProcess) {}
// Internal window id.
const uint64_t outerWindowId;
// URI of the document.
const nsCOMPtr<nsIURI> documentURI;
// Title of the document.
const nsString documentTitle;
// True if this is the toplevel window of the process.
// Note that this may be an iframe from another process.
const bool isProcessRoot;
const bool isInProcess;
};
// Info on a Utility process actor
struct UtilityInfo {
explicit UtilityInfo() : actorName(UtilityActorName::Unknown) {}
explicit UtilityInfo(UtilityActorName aActorName) : actorName(aActorName) {}
const UtilityActorName actorName;
};
struct ProcInfo {
// Process Id
base::ProcessId pid = 0;
// Child Id as defined by Firefox when a child process is created.
dom::ContentParentId childId;
// Process type
ProcType type;
// Origin, if any
nsCString origin;
// Memory size in bytes.
uint64_t memory = 0;
// CPU time in ns.
uint64_t cpuTime = 0;
uint64_t cpuCycleCount = 0;
// Threads owned by this process.
CopyableTArray<ThreadInfo> threads;
// DOM windows represented by this process.
CopyableTArray<WindowInfo> windows;
// Utility process actors, empty for non Utility process
CopyableTArray<UtilityInfo> utilityActors;
};
typedef MozPromise<mozilla::HashMap<base::ProcessId, ProcInfo>, nsresult, true>
ProcInfoPromise;
/**
* Data we need to request process info (e.g. CPU usage, memory usage)
* from the operating system and populate the resulting `ProcInfo`.
*
* Note that this structure contains a mix of:
* - low-level handles that we need to request low-level process info
* (`aChildTask` on macOS, `aPid` on other platforms); and
* - high-level data that we already acquired while looking for
* `aPid`/`aChildTask` and that we will need further down the road.
*/
struct ProcInfoRequest {
ProcInfoRequest(base::ProcessId aPid, ProcType aProcessType,
const nsACString& aOrigin, nsTArray<WindowInfo>&& aWindowInfo,
nsTArray<UtilityInfo>&& aUtilityInfo, uint32_t aChildId = 0
#ifdef XP_DARWIN
,
mach_port_t aChildTask = 0
#endif // XP_DARWIN
)
: pid(aPid),
processType(aProcessType),
origin(aOrigin),
windowInfo(std::move(aWindowInfo)),
utilityInfo(std::move(aUtilityInfo)),
childId(aChildId)
#ifdef XP_DARWIN
,
childTask(aChildTask)
#endif // XP_DARWIN
{
}
const base::ProcessId pid;
const ProcType processType;
const nsCString origin;
const nsTArray<WindowInfo> windowInfo;
const nsTArray<UtilityInfo> utilityInfo;
// If the process is a child, its child id, otherwise `0`.
const int32_t childId;
#ifdef XP_DARWIN
const mach_port_t childTask;
#endif // XP_DARWIN
};
/**
* Batch a request for low-level information on Gecko processes.
*
* # Request
*
* Argument `aRequests` is a list of processes, along with high-level data
* we have already obtained on them and that we need to populate the
* resulting array of `ProcInfo`.
*
* # Result
*
* This call succeeds (possibly with missing data, see below) unless we
* cannot allocate memory.
*
* # Performance
*
* - This call is always executed on a background thread.
* - This call does NOT wake up children processes.
* - This function is sometimes observably slow to resolve, in particular
* under Windows.
*
* # Error-handling and race conditions
*
* Requesting low-level information on a process and its threads is inherently
* subject to race conditions. Typically, if a process or a thread is killed
* while we're preparing to fetch information, we can easily end up with
* system/lib calls that return failures.
*
* For this reason, this API assumes that errors when placing a system/lib call
* are likely and normal. When some information cannot be obtained, the API will
* simply skip over said information.
*
* Note that due to different choices by OSes, the exact information we skip may
* vary across platforms. For instance, under Unix, failing to access the
* threads of a process will cause us to skip all data on the process, while
* under Windows, process information will be returned without thread
* information.
*/
RefPtr<ProcInfoPromise> GetProcInfo(nsTArray<ProcInfoRequest>&& aRequests);
/**
* Synchronous version of GetProcInfo.
*/
ProcInfoPromise::ResolveOrRejectValue GetProcInfoSync(
nsTArray<ProcInfoRequest>&& aRequests);
/**
* Utility function: copy data from a `ProcInfo` and into either a
* `ParentProcInfoDictionary` or a `ChildProcInfoDictionary`.
*/
template <typename T>
nsresult CopySysProcInfoToDOM(const ProcInfo& source, T* dest) {
// Copy system info.
dest->mPid = source.pid;
dest->mMemory = source.memory;
dest->mCpuTime = source.cpuTime;
dest->mCpuCycleCount = source.cpuCycleCount;
// Copy thread info.
mozilla::dom::Sequence<mozilla::dom::ThreadInfoDictionary> threads;
for (const ThreadInfo& entry : source.threads) {
mozilla::dom::ThreadInfoDictionary* thread =
threads.AppendElement(fallible);
if (NS_WARN_IF(!thread)) {
return NS_ERROR_OUT_OF_MEMORY;
}
thread->mCpuTime = entry.cpuTime;
thread->mCpuCycleCount = entry.cpuCycleCount;
thread->mTid = entry.tid;
thread->mName.Assign(entry.name);
}
dest->mThreads = std::move(threads);
return NS_OK;
}
} // namespace mozilla
#endif // ProcInfo_h
|