mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-25 05:41:12 +00:00
Bug 1529022 - Add a GeckoChildProcessHosts iterator r=jld
Adds GeckoChildProcessHost::GetAll() and use it in ChromeUtils::GetProcInfo() Differential Revision: https://phabricator.services.mozilla.com/D33920 --HG-- extra : moz-landing-system : lando
This commit is contained in:
parent
b8c27feb30
commit
9f31044be3
@ -30,6 +30,7 @@
|
||||
#include "mozilla/dom/UnionTypes.h"
|
||||
#include "mozilla/dom/WindowBinding.h" // For IdleRequestCallback/Options
|
||||
#include "mozilla/gfx/GPUProcessManager.h"
|
||||
#include "mozilla/ipc/GeckoChildProcessHost.h"
|
||||
#include "mozilla/net/UrlClassifierFeatureFactory.h"
|
||||
#include "mozilla/net/SocketProcessHost.h"
|
||||
#include "IOActivityMonitor.h"
|
||||
@ -692,67 +693,93 @@ already_AddRefed<Promise> ChromeUtils::RequestProcInfo(GlobalObject& aGlobal,
|
||||
->Then(
|
||||
target, __func__,
|
||||
[target, domPromise, parentPid](ProcInfo aParentInfo) {
|
||||
// Iterate over each child process to build an array of promises.
|
||||
nsTArray<ContentParent*> parents;
|
||||
ContentParent::GetAll(parents);
|
||||
// Get a list of ContentParent
|
||||
nsTArray<ContentParent*> contentParents;
|
||||
ContentParent::GetAll(contentParents);
|
||||
nsTArray<RefPtr<ProcInfoPromise>> promises;
|
||||
for (ContentParent* contentParent : parents) {
|
||||
// Getting the child process id.
|
||||
int32_t childPid = contentParent->Pid();
|
||||
if (childPid == -1) {
|
||||
continue;
|
||||
}
|
||||
// Converting the Content Type into a ProcType
|
||||
nsAutoString processType;
|
||||
processType.Assign(contentParent->GetRemoteType());
|
||||
mozilla::ProcType type = mozilla::ProcType::Unknown;
|
||||
if (processType.EqualsLiteral(DEFAULT_REMOTE_TYPE)) {
|
||||
type = mozilla::ProcType::Web;
|
||||
} else if (processType.EqualsLiteral(FILE_REMOTE_TYPE)) {
|
||||
type = mozilla::ProcType::File;
|
||||
} else if (processType.EqualsLiteral(EXTENSION_REMOTE_TYPE)) {
|
||||
type = mozilla::ProcType::Extension;
|
||||
} else if (processType.EqualsLiteral(
|
||||
PRIVILEGEDABOUT_REMOTE_TYPE)) {
|
||||
type = mozilla::ProcType::PrivilegedAbout;
|
||||
} else if (processType.EqualsLiteral(
|
||||
LARGE_ALLOCATION_REMOTE_TYPE)) {
|
||||
type = mozilla::ProcType::WebLargeAllocation;
|
||||
}
|
||||
mozilla::ipc::GeckoChildProcessHost::GetAll(
|
||||
[&promises, contentParents](
|
||||
mozilla::ipc::GeckoChildProcessHost* aGeckoProcess) {
|
||||
if (!aGeckoProcess->GetChildProcessHandle()) {
|
||||
return;
|
||||
}
|
||||
|
||||
promises.AppendElement(mozilla::GetProcInfo(
|
||||
(base::ProcessId)childPid, contentParent->ChildID(), type,
|
||||
contentParent->Process()));
|
||||
}
|
||||
base::ProcessId childPid =
|
||||
base::GetProcId(aGeckoProcess->GetChildProcessHandle());
|
||||
int32_t childId = 0;
|
||||
mozilla::ProcType type;
|
||||
switch (aGeckoProcess->GetProcessType()) {
|
||||
case GeckoProcessType::GeckoProcessType_Content: {
|
||||
ContentParent* contentParent = nullptr;
|
||||
// This loop can become slow as we get more processes in
|
||||
// Fission, so might need some refactoring in the future.
|
||||
for (ContentParent* parent : contentParents) {
|
||||
// find the match
|
||||
if (parent->Process() == aGeckoProcess) {
|
||||
contentParent = parent;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!contentParent) {
|
||||
return;
|
||||
}
|
||||
// Converting the Content Type into a ProcType
|
||||
nsAutoString processType;
|
||||
processType.Assign(contentParent->GetRemoteType());
|
||||
if (processType.EqualsLiteral(DEFAULT_REMOTE_TYPE)) {
|
||||
type = mozilla::ProcType::Web;
|
||||
} else if (processType.EqualsLiteral(FILE_REMOTE_TYPE)) {
|
||||
type = mozilla::ProcType::File;
|
||||
} else if (processType.EqualsLiteral(
|
||||
EXTENSION_REMOTE_TYPE)) {
|
||||
type = mozilla::ProcType::Extension;
|
||||
} else if (processType.EqualsLiteral(
|
||||
PRIVILEGEDABOUT_REMOTE_TYPE)) {
|
||||
type = mozilla::ProcType::PrivilegedAbout;
|
||||
} else if (processType.EqualsLiteral(
|
||||
LARGE_ALLOCATION_REMOTE_TYPE)) {
|
||||
type = mozilla::ProcType::WebLargeAllocation;
|
||||
}
|
||||
childId = contentParent->ChildID();
|
||||
break;
|
||||
}
|
||||
case GeckoProcessType::GeckoProcessType_Default:
|
||||
type = mozilla::ProcType::Browser;
|
||||
break;
|
||||
case GeckoProcessType::GeckoProcessType_Plugin:
|
||||
type = mozilla::ProcType::Plugin;
|
||||
break;
|
||||
case GeckoProcessType::GeckoProcessType_GMPlugin:
|
||||
type = mozilla::ProcType::GMPlugin;
|
||||
break;
|
||||
case GeckoProcessType::GeckoProcessType_GPU:
|
||||
type = mozilla::ProcType::GPU;
|
||||
break;
|
||||
case GeckoProcessType::GeckoProcessType_VR:
|
||||
type = mozilla::ProcType::VR;
|
||||
break;
|
||||
case GeckoProcessType::GeckoProcessType_RDD:
|
||||
type = mozilla::ProcType::RDD;
|
||||
break;
|
||||
case GeckoProcessType::GeckoProcessType_Socket:
|
||||
type = mozilla::ProcType::Socket;
|
||||
break;
|
||||
case GeckoProcessType::GeckoProcessType_RemoteSandboxBroker:
|
||||
type = mozilla::ProcType::RemoteSandboxBroker;
|
||||
break;
|
||||
default:
|
||||
type = mozilla::ProcType::Unknown;
|
||||
}
|
||||
|
||||
// Getting the Socket Process
|
||||
int32_t SocketPid = net::gIOService->SocketProcessPid();
|
||||
if (SocketPid != 0) {
|
||||
promises.AppendElement(mozilla::GetProcInfo(
|
||||
(base::ProcessId)SocketPid, 0, mozilla::ProcType::Socket,
|
||||
net::gIOService->SocketProcess()));
|
||||
}
|
||||
|
||||
// Getting the GPU and RDD processes on supported platforms
|
||||
gfx::GPUProcessManager* pm = gfx::GPUProcessManager::Get();
|
||||
if (pm) {
|
||||
base::ProcessId GpuPid = pm->GPUProcessPid();
|
||||
if (GpuPid != -1) {
|
||||
promises.AppendElement(mozilla::GetProcInfo(
|
||||
GpuPid, 0, mozilla::ProcType::Gpu, pm->Process()));
|
||||
}
|
||||
}
|
||||
RDDProcessManager* RDDPm = RDDProcessManager::Get();
|
||||
if (RDDPm) {
|
||||
base::ProcessId RDDPid = RDDPm->RDDProcessPid();
|
||||
if (RDDPid != -1) {
|
||||
promises.AppendElement(mozilla::GetProcInfo(
|
||||
RDDPid, 0, mozilla::ProcType::Rdd, RDDPm->Process()));
|
||||
}
|
||||
}
|
||||
|
||||
// two more processes to add: VR and GMP
|
||||
// see https://bugzilla.mozilla.org/show_bug.cgi?id=1529022
|
||||
promises.AppendElement(
|
||||
#ifdef XP_MACOSX
|
||||
mozilla::GetProcInfo(childPid, childId, type,
|
||||
aGeckoProcess->GetChildTask())
|
||||
#else
|
||||
mozilla::GetProcInfo(childPid, childId, type)
|
||||
#endif
|
||||
);
|
||||
});
|
||||
|
||||
auto ProcInfoResolver =
|
||||
[domPromise, parentPid, parentInfo = aParentInfo](
|
||||
|
@ -37,6 +37,7 @@
|
||||
|
||||
#include "mozilla/ipc/BrowserProcessSubThread.h"
|
||||
#include "mozilla/ipc/EnvironmentMap.h"
|
||||
#include "mozilla/LinkedList.h"
|
||||
#include "mozilla/Omnijar.h"
|
||||
#include "mozilla/RecordReplay.h"
|
||||
#include "mozilla/RDDProcessHost.h"
|
||||
@ -102,6 +103,11 @@ static bool ShouldHaveDirectoryService() {
|
||||
return GeckoProcessType_Default == XRE_GetProcessType();
|
||||
}
|
||||
|
||||
StaticAutoPtr<mozilla::LinkedList<GeckoChildProcessHost>>
|
||||
GeckoChildProcessHost::sGeckoChildProcessHosts;
|
||||
|
||||
StaticMutex GeckoChildProcessHost::sMutex;
|
||||
|
||||
GeckoChildProcessHost::GeckoChildProcessHost(GeckoProcessType aProcessType,
|
||||
bool aIsFileContent)
|
||||
: mProcessType(aProcessType),
|
||||
@ -122,6 +128,11 @@ GeckoChildProcessHost::GeckoChildProcessHost(GeckoProcessType aProcessType,
|
||||
#endif
|
||||
mDestroying(false) {
|
||||
MOZ_COUNT_CTOR(GeckoChildProcessHost);
|
||||
StaticMutexAutoLock lock(sMutex);
|
||||
if (!sGeckoChildProcessHosts) {
|
||||
sGeckoChildProcessHosts = new mozilla::LinkedList<GeckoChildProcessHost>();
|
||||
}
|
||||
sGeckoChildProcessHosts->insertBack(this);
|
||||
}
|
||||
|
||||
GeckoChildProcessHost::~GeckoChildProcessHost()
|
||||
@ -168,8 +179,19 @@ GeckoChildProcessHost::~GeckoChildProcessHost()
|
||||
#endif
|
||||
}
|
||||
|
||||
void GeckoChildProcessHost::RemoveFromProcessList() {
|
||||
StaticMutexAutoLock lock(sMutex);
|
||||
if (!sGeckoChildProcessHosts) {
|
||||
return;
|
||||
}
|
||||
LinkedListElement<GeckoChildProcessHost>::removeFrom(
|
||||
*sGeckoChildProcessHosts);
|
||||
}
|
||||
|
||||
void GeckoChildProcessHost::Destroy() {
|
||||
MOZ_RELEASE_ASSERT(!mDestroying);
|
||||
// We can remove from the list before it's really destroyed
|
||||
RemoveFromProcessList();
|
||||
RefPtr<HandlePromise> whenReady = mHandlePromise;
|
||||
|
||||
if (!whenReady) {
|
||||
@ -1459,3 +1481,13 @@ bool GeckoChildProcessHost::StartMacSandbox(int aArgc, char** aArgv,
|
||||
}
|
||||
|
||||
#endif /* XP_MACOSX && MOZ_SANDBOX */
|
||||
|
||||
/* static */
|
||||
void GeckoChildProcessHost::GetAll(const GeckoProcessCallback& aCallback) {
|
||||
StaticMutexAutoLock lock(sMutex);
|
||||
for (GeckoChildProcessHost* gp = sGeckoChildProcessHosts->getFirst(); gp;
|
||||
gp = static_cast<mozilla::LinkedListElement<GeckoChildProcessHost>*>(gp)
|
||||
->getNext()) {
|
||||
aCallback(gp);
|
||||
}
|
||||
}
|
||||
|
@ -14,6 +14,7 @@
|
||||
|
||||
#include "mozilla/ipc/FileDescriptor.h"
|
||||
#include "mozilla/Atomics.h"
|
||||
#include "mozilla/LinkedList.h"
|
||||
#include "mozilla/Monitor.h"
|
||||
#include "mozilla/MozPromise.h"
|
||||
#include "mozilla/StaticPtr.h"
|
||||
@ -37,7 +38,8 @@ typedef _MacSandboxInfo MacSandboxInfo;
|
||||
namespace mozilla {
|
||||
namespace ipc {
|
||||
|
||||
class GeckoChildProcessHost : public ChildProcessHost {
|
||||
class GeckoChildProcessHost : public ChildProcessHost,
|
||||
public LinkedListElement<GeckoChildProcessHost> {
|
||||
protected:
|
||||
typedef mozilla::Monitor Monitor;
|
||||
typedef std::vector<std::string> StringVector;
|
||||
@ -153,10 +155,15 @@ class GeckoChildProcessHost : public ChildProcessHost {
|
||||
return MacSandboxType_Utility;
|
||||
};
|
||||
#endif
|
||||
typedef std::function<void(GeckoChildProcessHost*)> GeckoProcessCallback;
|
||||
|
||||
// Iterates over all instances and calls aCallback with each one of them.
|
||||
// This method will lock any addition/removal of new processes
|
||||
// so you need to make sure the callback is as fast as possible.
|
||||
static void GetAll(const GeckoProcessCallback& aCallback);
|
||||
|
||||
protected:
|
||||
~GeckoChildProcessHost();
|
||||
|
||||
GeckoProcessType mProcessType;
|
||||
bool mIsFileContent;
|
||||
Monitor mMonitor;
|
||||
@ -241,6 +248,9 @@ class GeckoChildProcessHost : public ChildProcessHost {
|
||||
// with launching the sub-process.
|
||||
void GetChildLogName(const char* origLogName, nsACString& buffer);
|
||||
|
||||
// Removes the instance from sGeckoChildProcessHosts
|
||||
void RemoveFromProcessList();
|
||||
|
||||
// In between launching the subprocess and handing off its IPC
|
||||
// channel, there's a small window of time in which *we* might still
|
||||
// be the channel listener, and receive messages. That's bad
|
||||
@ -258,7 +268,9 @@ class GeckoChildProcessHost : public ChildProcessHost {
|
||||
mozilla::Atomic<bool> mDestroying;
|
||||
|
||||
static uint32_t sNextUniqueID;
|
||||
|
||||
static StaticAutoPtr<LinkedList<GeckoChildProcessHost>>
|
||||
sGeckoChildProcessHosts;
|
||||
static StaticMutex sMutex;
|
||||
#if defined(MOZ_WIDGET_ANDROID)
|
||||
void LaunchAndroidService(
|
||||
const char* type, const std::vector<std::string>& argv,
|
||||
|
@ -24,14 +24,16 @@ enum class ProcType {
|
||||
Extension,
|
||||
PrivilegedAbout,
|
||||
WebLargeAllocation,
|
||||
// GPU process (only on Windows)
|
||||
Gpu,
|
||||
// RDD process (Windows and macOS)
|
||||
Rdd,
|
||||
// Socket process
|
||||
// the rest matches GeckoProcessTypes.h
|
||||
Browser, // Default is named Browser here
|
||||
Plugin,
|
||||
IPDLUnitTest,
|
||||
GMPlugin,
|
||||
GPU,
|
||||
VR,
|
||||
RDD,
|
||||
Socket,
|
||||
// Main process
|
||||
Browser,
|
||||
RemoteSandboxBroker,
|
||||
// Unknown type of process
|
||||
Unknown
|
||||
};
|
||||
@ -76,9 +78,14 @@ typedef MozPromise<ProcInfo, nsresult, true> ProcInfoPromise;
|
||||
* Depending on the platform, this call can be quite expensive and the
|
||||
* promise may return after several ms.
|
||||
*/
|
||||
RefPtr<ProcInfoPromise> GetProcInfo(
|
||||
base::ProcessId pid, int32_t childId, const ProcType& type,
|
||||
ipc::GeckoChildProcessHost* childProcess = nullptr);
|
||||
#ifdef XP_MACOSX
|
||||
RefPtr<ProcInfoPromise> GetProcInfo(base::ProcessId pid, int32_t childId,
|
||||
const ProcType& type,
|
||||
mach_port_t aChildTask = MACH_PORT_NULL);
|
||||
#else
|
||||
RefPtr<ProcInfoPromise> GetProcInfo(base::ProcessId pid, int32_t childId,
|
||||
const ProcType& type);
|
||||
#endif
|
||||
|
||||
} // namespace mozilla
|
||||
#endif // ProcInfo_h
|
||||
|
@ -10,8 +10,7 @@
|
||||
namespace mozilla {
|
||||
|
||||
RefPtr<ProcInfoPromise> GetProcInfo(base::ProcessId pid, int32_t childId,
|
||||
const ProcType& type,
|
||||
ipc::GeckoChildProcessHost* childProcess) {
|
||||
const ProcType& type) {
|
||||
// Not implemented on Android.
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -20,7 +20,7 @@
|
||||
namespace mozilla {
|
||||
|
||||
RefPtr<ProcInfoPromise> GetProcInfo(base::ProcessId pid, int32_t childId, const ProcType& type,
|
||||
ipc::GeckoChildProcessHost* childProcess) {
|
||||
mach_port_t aChildTask) {
|
||||
auto holder = MakeUnique<MozPromiseHolder<ProcInfoPromise>>();
|
||||
RefPtr<ProcInfoPromise> promise = holder->Ensure(__func__);
|
||||
|
||||
@ -32,12 +32,7 @@ RefPtr<ProcInfoPromise> GetProcInfo(base::ProcessId pid, int32_t childId, const
|
||||
return promise;
|
||||
}
|
||||
|
||||
mach_port_t task = MACH_PORT_NULL;
|
||||
if (childProcess && childProcess->GetChildTask() != MACH_PORT_NULL) {
|
||||
task = childProcess->GetChildTask();
|
||||
}
|
||||
|
||||
auto ResolveGetProcinfo = [holder = std::move(holder), pid, type, childId, task]() {
|
||||
auto ResolveGetProcinfo = [holder = std::move(holder), pid, type, childId, aChildTask]() {
|
||||
ProcInfo info;
|
||||
info.pid = pid;
|
||||
info.childId = childId;
|
||||
@ -66,10 +61,10 @@ RefPtr<ProcInfoPromise> GetProcInfo(base::ProcessId pid, int32_t childId, const
|
||||
// Now getting threads info
|
||||
mach_port_t selectedTask;
|
||||
// If we did not get a task from a child process, we use mach_task_self()
|
||||
if (task == MACH_PORT_NULL) {
|
||||
if (aChildTask == MACH_PORT_NULL) {
|
||||
selectedTask = mach_task_self();
|
||||
} else {
|
||||
selectedTask = task;
|
||||
selectedTask = aChildTask;
|
||||
}
|
||||
// task_threads() gives us a snapshot of the process threads
|
||||
// but those threads can go away. All the code below makes
|
||||
|
@ -208,8 +208,7 @@ class ThreadInfoReader final : public StatReader {
|
||||
};
|
||||
|
||||
RefPtr<ProcInfoPromise> GetProcInfo(base::ProcessId pid, int32_t childId,
|
||||
const ProcType& type,
|
||||
ipc::GeckoChildProcessHost* childProcess) {
|
||||
const ProcType& type) {
|
||||
auto holder = MakeUnique<MozPromiseHolder<ProcInfoPromise>>();
|
||||
RefPtr<ProcInfoPromise> promise = holder->Ensure(__func__);
|
||||
nsresult rv = NS_OK;
|
||||
|
@ -73,8 +73,7 @@ void AppendThreads(ProcInfo* info) {
|
||||
}
|
||||
|
||||
RefPtr<ProcInfoPromise> GetProcInfo(base::ProcessId pid, int32_t childId,
|
||||
const ProcType& type,
|
||||
ipc::GeckoChildProcessHost* childProcess) {
|
||||
const ProcType& type) {
|
||||
auto holder = MakeUnique<MozPromiseHolder<ProcInfoPromise>>();
|
||||
RefPtr<ProcInfoPromise> promise = holder->Ensure(__func__);
|
||||
|
||||
|
@ -20,7 +20,8 @@
|
||||
// said values are exposed to things like telemetry as well, so please
|
||||
// do not reorder lines in this file.
|
||||
//
|
||||
// Please add new process types at the end of this list.
|
||||
// Please add new process types at the end of this list
|
||||
// and update widget/ProcInfo.h
|
||||
GECKO_PROCESS_TYPE(Default, "default", Parent, Self)
|
||||
GECKO_PROCESS_TYPE(Plugin, "plugin", Plugin, PluginContainer)
|
||||
GECKO_PROCESS_TYPE(Content, "tab", Content, Self)
|
||||
|
Loading…
Reference in New Issue
Block a user