mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-23 12:51:06 +00:00
Bug 1440207 - Part 3d: Pass the initial IPC pipe using geckoargs, r=ipc-reviewers,mccr8
The initial IPC pipe was previously the only argument passed as a chromium command line flag. This changes it to instead be passed using geckoargs, unifying the platforms, and removing the need for specific handling on every platform. Differential Revision: https://phabricator.services.mozilla.com/D221374
This commit is contained in:
parent
3c8b71811d
commit
fd1d20ea4b
@ -58,9 +58,10 @@ static nsresult GetGREDir(nsIFile** aResult) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
ContentProcess::ContentProcess(ProcessId aParentPid,
|
||||
ContentProcess::ContentProcess(IPC::Channel::ChannelHandle aClientChannel,
|
||||
ProcessId aParentPid,
|
||||
const nsID& aMessageChannelId)
|
||||
: ProcessChild(aParentPid, aMessageChannelId) {
|
||||
: ProcessChild(std::move(aClientChannel), aParentPid, aMessageChannelId) {
|
||||
NS_LogInit();
|
||||
}
|
||||
|
||||
|
@ -25,7 +25,8 @@ class ContentProcess : public mozilla::ipc::ProcessChild {
|
||||
using ProcessChild = mozilla::ipc::ProcessChild;
|
||||
|
||||
public:
|
||||
ContentProcess(ProcessId aParentPid, const nsID& aMessageChannelId);
|
||||
ContentProcess(IPC::Channel::ChannelHandle aClientChannel,
|
||||
ProcessId aParentPid, const nsID& aMessageChannelId);
|
||||
~ContentProcess();
|
||||
|
||||
virtual bool Init(int aArgc, char* aArgv[]) override;
|
||||
|
@ -9,10 +9,13 @@
|
||||
#include "chrome/common/child_process.h"
|
||||
#include "mozilla/ipc/NodeController.h"
|
||||
|
||||
ChildThread::ChildThread(Thread::Options options, base::ProcessId parent_pid)
|
||||
ChildThread::ChildThread(Thread::Options options,
|
||||
IPC::Channel::ChannelHandle client_handle,
|
||||
base::ProcessId parent_pid)
|
||||
: Thread("IPC I/O Child"),
|
||||
owner_loop_(MessageLoop::current()),
|
||||
options_(options),
|
||||
client_handle_(std::move(client_handle)),
|
||||
parent_pid_(parent_pid) {
|
||||
DCHECK(owner_loop_);
|
||||
}
|
||||
@ -31,10 +34,8 @@ ChildThread* ChildThread::current() {
|
||||
void ChildThread::Init() {
|
||||
// Take ownership of the client channel handle which we inherited, and use it
|
||||
// to start the initial IPC connection to the parent process.
|
||||
IPC::Channel::ChannelHandle client_handle(
|
||||
IPC::Channel::GetClientChannelHandle());
|
||||
auto channel = mozilla::MakeUnique<IPC::Channel>(
|
||||
std::move(client_handle), IPC::Channel::MODE_CLIENT, parent_pid_);
|
||||
std::move(client_handle_), IPC::Channel::MODE_CLIENT, parent_pid_);
|
||||
#if defined(XP_WIN)
|
||||
channel->StartAcceptingHandles(IPC::Channel::MODE_CLIENT);
|
||||
#elif defined(XP_DARWIN)
|
||||
|
@ -19,7 +19,9 @@ class ResourceDispatcher;
|
||||
class ChildThread : public base::Thread {
|
||||
public:
|
||||
// Creates the thread.
|
||||
ChildThread(Thread::Options options, base::ProcessId parent_pid);
|
||||
ChildThread(Thread::Options options,
|
||||
IPC::Channel::ChannelHandle client_handle,
|
||||
base::ProcessId parent_pid);
|
||||
virtual ~ChildThread();
|
||||
|
||||
mozilla::ipc::ScopedPort TakeInitialPort() {
|
||||
@ -48,6 +50,8 @@ class ChildThread : public base::Thread {
|
||||
|
||||
Thread::Options options_;
|
||||
|
||||
IPC::Channel::ChannelHandle client_handle_;
|
||||
|
||||
base::ProcessId parent_pid_;
|
||||
|
||||
DISALLOW_EVIL_CONSTRUCTORS(ChildThread);
|
||||
|
@ -142,18 +142,6 @@ class Channel {
|
||||
void StartAcceptingHandles(Mode mode);
|
||||
#endif
|
||||
|
||||
#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_UIKIT)
|
||||
// Used to set the first IPC file descriptor in the child process on
|
||||
// Android and iOS. See ipc_channel_posix.cc for further details on how this
|
||||
// is used.
|
||||
static void SetClientChannelFd(int fd);
|
||||
#endif // defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_UIKIT)
|
||||
|
||||
// Get the first IPC channel handle in the child process. This will have been
|
||||
// set by SetClientChannelFd on Android, will be a constant on other unix
|
||||
// platforms, or will have been passed on the command line on Windows.
|
||||
static ChannelHandle::ElementType GetClientChannelHandle();
|
||||
|
||||
// Create a new pair of pipe endpoints which can be used to establish a
|
||||
// native IPC::Channel connection.
|
||||
static bool CreateRawPipe(ChannelHandle* server, ChannelHandle* client);
|
||||
|
@ -59,41 +59,9 @@ using namespace mozilla::ipc;
|
||||
|
||||
namespace IPC {
|
||||
|
||||
// IPC channels on Windows use named pipes (CreateNamedPipe()) with
|
||||
// channel ids as the pipe names. Channels on POSIX use anonymous
|
||||
// Unix domain sockets created via socketpair() as pipes. These don't
|
||||
// quite line up.
|
||||
//
|
||||
// When creating a child subprocess, the parent side of the fork
|
||||
// arranges it such that the initial control channel ends up on the
|
||||
// magic file descriptor gClientChannelFd in the child. Future
|
||||
// connections (file descriptors) can then be passed via that
|
||||
// connection via sendmsg().
|
||||
//
|
||||
// On Android, child processes are created as a service instead of
|
||||
// forking the parent process. The Android Binder service is used to
|
||||
// transport the IPC channel file descriptor to the child process.
|
||||
// So rather than re-mapping the file descriptor to a known value,
|
||||
// the received channel file descriptor is set by calling
|
||||
// SetClientChannelFd before gecko has been initialized and started
|
||||
// in the child process.
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
namespace {
|
||||
|
||||
// This is the file descriptor number that a client process expects to find its
|
||||
// IPC socket.
|
||||
static int gClientChannelFd =
|
||||
#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_UIKIT)
|
||||
// On android/ios the fd is set at the time of child creation.
|
||||
-1
|
||||
#else
|
||||
3
|
||||
#endif // defined(MOZ_WIDGET_ANDROID)
|
||||
;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
bool ErrorIsBrokenPipe(int err) { return err == EPIPE || err == ECONNRESET; }
|
||||
|
||||
// Some Android ARM64 devices appear to have a bug where sendmsg
|
||||
@ -135,12 +103,6 @@ static inline ssize_t corrected_sendmsg(int socket,
|
||||
} // namespace
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_UIKIT)
|
||||
void Channel::SetClientChannelFd(int fd) { gClientChannelFd = fd; }
|
||||
#endif // defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_UIKIT)
|
||||
|
||||
int Channel::GetClientChannelHandle() { return gClientChannelFd; }
|
||||
|
||||
Channel::ChannelImpl::ChannelImpl(ChannelHandle pipe, Mode mode,
|
||||
base::ProcessId other_pid)
|
||||
: chan_cap_("ChannelImpl::SendMutex",
|
||||
|
@ -755,16 +755,6 @@ void Channel::SetOtherPid(base::ProcessId other_pid) {
|
||||
|
||||
bool Channel::IsClosed() const { return channel_impl_->IsClosed(); }
|
||||
|
||||
HANDLE Channel::GetClientChannelHandle() {
|
||||
// Read the switch from the command line which passed the initial handle for
|
||||
// this process, and convert it back into a HANDLE.
|
||||
std::wstring switchValue = CommandLine::ForCurrentProcess()->GetSwitchValue(
|
||||
switches::kProcessChannelID);
|
||||
|
||||
uint32_t handleInt = std::stoul(switchValue);
|
||||
return Uint32ToHandle(handleInt);
|
||||
}
|
||||
|
||||
// static
|
||||
bool Channel::CreateRawPipe(ChannelHandle* server, ChannelHandle* client) {
|
||||
std::wstring pipe_name =
|
||||
|
@ -254,7 +254,6 @@ class BaseProcessLauncher {
|
||||
char mChildIDString[32];
|
||||
|
||||
// Set during launch.
|
||||
IPC::Channel::ChannelHandle mClientChannelHandle;
|
||||
nsCOMPtr<nsIFile> mAppDir;
|
||||
};
|
||||
|
||||
@ -287,16 +286,13 @@ class PosixProcessLauncher : public BaseProcessLauncher {
|
||||
PosixProcessLauncher(GeckoChildProcessHost* aHost,
|
||||
geckoargs::ChildProcessArgs&& aExtraOpts)
|
||||
: BaseProcessLauncher(aHost, std::move(aExtraOpts)),
|
||||
mProfileDir(aHost->mProfileDir),
|
||||
mChannelDstFd(IPC::Channel::GetClientChannelHandle()) {}
|
||||
mProfileDir(aHost->mProfileDir) {}
|
||||
|
||||
protected:
|
||||
virtual Result<Ok, LaunchError> DoSetup() override;
|
||||
virtual RefPtr<ProcessHandlePromise> DoLaunch() override;
|
||||
|
||||
nsCOMPtr<nsIFile> mProfileDir;
|
||||
|
||||
int mChannelDstFd;
|
||||
};
|
||||
|
||||
# if defined(XP_MACOSX)
|
||||
@ -1173,11 +1169,11 @@ void BaseProcessLauncher::MapChildLogging() {
|
||||
}
|
||||
|
||||
Result<Ok, LaunchError> BaseProcessLauncher::DoFinishLaunch() {
|
||||
// We're in the parent and the child was launched. Close the child channel
|
||||
// handle in the parent as soon as possible, which will allow the parent to
|
||||
// detect when the child closes its handle (either due to normal exit or due
|
||||
// to crash).
|
||||
mClientChannelHandle = nullptr;
|
||||
// We're in the parent and the child was launched. Clean up any FDs which were
|
||||
// transferred to the child in the parent as soon as possible, which will
|
||||
// allow the parent to detect when the child closes its handle (either due to
|
||||
// normal exit or due to crash).
|
||||
mChildArgs.mFiles.clear();
|
||||
|
||||
return Ok();
|
||||
}
|
||||
@ -1263,22 +1259,6 @@ Result<Ok, LaunchError> PosixProcessLauncher::DoSetup() {
|
||||
FilePath exePath;
|
||||
BinPathType pathType = GetPathToBinary(exePath, mProcessType);
|
||||
|
||||
// remap the IPC socket fd to a well-known int, as the OS does for
|
||||
// STDOUT_FILENO, for example
|
||||
// The fork server doesn't use IPC::Channel, so can skip this step.
|
||||
if (mProcessType != GeckoProcessType_ForkServer) {
|
||||
# if !defined(MOZ_WIDGET_ANDROID) && !defined(MOZ_WIDGET_UIKIT)
|
||||
// On Android/iOS, mChannelDstFd is initialised to -1 and the launching
|
||||
// code uses only the first of each pair.
|
||||
MOZ_ASSERT(mChannelDstFd >= 0);
|
||||
# endif
|
||||
mLaunchOptions->fds_to_remap.push_back(
|
||||
std::pair<int, int>(mClientChannelHandle.get(), mChannelDstFd));
|
||||
}
|
||||
|
||||
// no need for kProcessChannelID, the child process inherits the
|
||||
// other end of the socketpair() from us
|
||||
|
||||
// Make sure the executable path is present at the start of our argument list.
|
||||
// If we're using BinPathType::Self, also add the `-contentproc` argument.
|
||||
if (pathType == BinPathType::Self) {
|
||||
@ -1587,16 +1567,8 @@ Result<Ok, LaunchError> WindowsProcessLauncher::DoSetup() {
|
||||
}
|
||||
# endif // HAS_DLL_BLOCKLIST
|
||||
|
||||
// Inherit the initial client channel handle into the child process.
|
||||
std::wstring processChannelID =
|
||||
std::to_wstring(uint32_t(uintptr_t(mClientChannelHandle.get())));
|
||||
mLaunchOptions->handles_to_inherit.push_back(mClientChannelHandle.get());
|
||||
mCmdLine->AppendSwitchWithValue(switches::kProcessChannelID,
|
||||
processChannelID);
|
||||
|
||||
for (std::vector<std::string>::iterator it = mExtraOpts.begin();
|
||||
it != mExtraOpts.end(); ++it) {
|
||||
mCmdLine->AppendLooseValue(UTF8ToWide(*it));
|
||||
for (const std::string& arg : mChildArgs.mArgs) {
|
||||
mCmdLine->AppendLooseValue(UTF8ToWide(arg));
|
||||
}
|
||||
|
||||
# if defined(MOZ_SANDBOX)
|
||||
@ -1937,11 +1909,13 @@ RefPtr<ProcessLaunchPromise> BaseProcessLauncher::Launch(
|
||||
// initializing it.
|
||||
if (mProcessType != GeckoProcessType_ForkServer) {
|
||||
IPC::Channel::ChannelHandle serverHandle;
|
||||
if (!IPC::Channel::CreateRawPipe(&serverHandle, &mClientChannelHandle)) {
|
||||
IPC::Channel::ChannelHandle clientHandle;
|
||||
if (!IPC::Channel::CreateRawPipe(&serverHandle, &clientHandle)) {
|
||||
return ProcessLaunchPromise::CreateAndReject(LaunchError("CreateRawPipe"),
|
||||
__func__);
|
||||
}
|
||||
aHost->InitializeChannel(std::move(serverHandle));
|
||||
geckoargs::sIPCHandle.Put(std::move(clientHandle), mChildArgs);
|
||||
}
|
||||
|
||||
return InvokeAsync(mLaunchThread, this, __func__,
|
||||
|
@ -20,10 +20,11 @@ namespace ipc {
|
||||
// IPC IO MessageLoop lives.
|
||||
class IOThreadChild : public ChildThread {
|
||||
public:
|
||||
explicit IOThreadChild(base::ProcessId aParentPid)
|
||||
explicit IOThreadChild(IPC::Channel::ChannelHandle aClientChannel,
|
||||
base::ProcessId aParentPid)
|
||||
: ChildThread(base::Thread::Options(MessageLoop::TYPE_IO,
|
||||
/* stack size */ 0),
|
||||
aParentPid) {}
|
||||
std::move(aClientChannel), aParentPid) {}
|
||||
|
||||
~IOThreadChild() = default;
|
||||
|
||||
|
@ -33,8 +33,9 @@ nsCString ProcessChild::gIPCShutdownStateAnnotation;
|
||||
|
||||
static Atomic<bool> sExpectingShutdown(false);
|
||||
|
||||
ProcessChild::ProcessChild(ProcessId aParentPid, const nsID& aMessageChannelId)
|
||||
: ChildProcess(new IOThreadChild(aParentPid)),
|
||||
ProcessChild::ProcessChild(IPC::Channel::ChannelHandle aClientChannel,
|
||||
ProcessId aParentPid, const nsID& aMessageChannelId)
|
||||
: ChildProcess(new IOThreadChild(std::move(aClientChannel), aParentPid)),
|
||||
mUILoop(MessageLoop::current()),
|
||||
mParentPid(aParentPid),
|
||||
mMessageChannelId(aMessageChannelId) {
|
||||
|
@ -27,7 +27,8 @@ class ProcessChild : public ChildProcess {
|
||||
typedef base::ProcessId ProcessId;
|
||||
|
||||
public:
|
||||
explicit ProcessChild(ProcessId aParentPid, const nsID& aMessageChannelId);
|
||||
explicit ProcessChild(IPC::Channel::ChannelHandle aClientChannel,
|
||||
ProcessId aParentPid, const nsID& aMessageChannelId);
|
||||
|
||||
ProcessChild(const ProcessChild&) = delete;
|
||||
ProcessChild& operator=(const ProcessChild&) = delete;
|
||||
|
@ -295,14 +295,15 @@ class IPDLUnitTestProcessChild : public ipc::ProcessChild {
|
||||
|
||||
// Defined in nsEmbedFunctions.cpp
|
||||
extern UniquePtr<ipc::ProcessChild> (*gMakeIPDLUnitTestProcessChild)(
|
||||
base::ProcessId, const nsID&);
|
||||
IPC::Channel::ChannelHandle, base::ProcessId, const nsID&);
|
||||
|
||||
// Initialize gMakeIPDLUnitTestProcessChild in a static constructor.
|
||||
int _childProcessEntryPointStaticConstructor = ([] {
|
||||
gMakeIPDLUnitTestProcessChild =
|
||||
[](base::ProcessId aParentPid,
|
||||
[](IPC::Channel::ChannelHandle aClientChannel, base::ProcessId aParentPid,
|
||||
const nsID& aMessageChannelId) -> UniquePtr<ipc::ProcessChild> {
|
||||
return MakeUnique<IPDLUnitTestProcessChild>(aParentPid, aMessageChannelId);
|
||||
return MakeUnique<IPDLUnitTestProcessChild>(std::move(aClientChannel),
|
||||
aParentPid, aMessageChannelId);
|
||||
};
|
||||
return 0;
|
||||
})();
|
||||
|
@ -148,6 +148,8 @@ static CommandLineArg<const char*> sGREOmni{"-greomni", "greomni"};
|
||||
static CommandLineArg<const char*> sAppOmni{"-appomni", "appomni"};
|
||||
static CommandLineArg<const char*> sProfile{"-profile", "profile"};
|
||||
|
||||
static CommandLineArg<UniqueFileHandle> sIPCHandle{"-ipcHandle", "ipchandle"};
|
||||
|
||||
static CommandLineArg<UniqueFileHandle> sJsInitHandle{"-jsInitHandle",
|
||||
"jsinithandle"};
|
||||
static CommandLineArg<uint64_t> sJsInitLen{"-jsInitLen", "jsinitlen"};
|
||||
|
@ -147,7 +147,7 @@ using mozilla::ipc::TestShellParent;
|
||||
namespace mozilla::_ipdltest {
|
||||
// Set in IPDLUnitTest.cpp when running gtests.
|
||||
UniquePtr<mozilla::ipc::ProcessChild> (*gMakeIPDLUnitTestProcessChild)(
|
||||
base::ProcessId, const nsID&) = nullptr;
|
||||
IPC::Channel::ChannelHandle, base::ProcessId, const nsID&) = nullptr;
|
||||
} // namespace mozilla::_ipdltest
|
||||
|
||||
static NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID);
|
||||
@ -445,7 +445,9 @@ nsresult XRE_InitChildProcess(int aArgc, char* aArgv[],
|
||||
Maybe<base::ProcessId> parentPID = geckoargs::sParentPid.Get(aArgc, aArgv);
|
||||
Maybe<const char*> initialChannelIdString =
|
||||
geckoargs::sInitialChannelID.Get(aArgc, aArgv);
|
||||
if (NS_WARN_IF(!parentPID || !initialChannelIdString)) {
|
||||
Maybe<IPC::Channel::ChannelHandle> clientChannel =
|
||||
geckoargs::sIPCHandle.Get(aArgc, aArgv);
|
||||
if (NS_WARN_IF(!parentPID || !initialChannelIdString || !clientChannel)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
@ -520,50 +522,52 @@ nsresult XRE_InitChildProcess(int aArgc, char* aArgv[],
|
||||
|
||||
case GeckoProcessType_Content:
|
||||
ioInterposerGuard.Init();
|
||||
process = MakeUnique<ContentProcess>(*parentPID, messageChannelId);
|
||||
process = MakeUnique<ContentProcess>(std::move(*clientChannel),
|
||||
*parentPID, messageChannelId);
|
||||
break;
|
||||
|
||||
case GeckoProcessType_IPDLUnitTest:
|
||||
MOZ_RELEASE_ASSERT(mozilla::_ipdltest::gMakeIPDLUnitTestProcessChild,
|
||||
"xul-gtest not loaded!");
|
||||
process = mozilla::_ipdltest::gMakeIPDLUnitTestProcessChild(
|
||||
*parentPID, messageChannelId);
|
||||
std::move(*clientChannel), *parentPID, messageChannelId);
|
||||
break;
|
||||
|
||||
case GeckoProcessType_GMPlugin:
|
||||
process =
|
||||
MakeUnique<gmp::GMPProcessChild>(*parentPID, messageChannelId);
|
||||
process = MakeUnique<gmp::GMPProcessChild>(
|
||||
std::move(*clientChannel), *parentPID, messageChannelId);
|
||||
break;
|
||||
|
||||
case GeckoProcessType_GPU:
|
||||
process =
|
||||
MakeUnique<gfx::GPUProcessImpl>(*parentPID, messageChannelId);
|
||||
process = MakeUnique<gfx::GPUProcessImpl>(
|
||||
std::move(*clientChannel), *parentPID, messageChannelId);
|
||||
break;
|
||||
|
||||
case GeckoProcessType_VR:
|
||||
process =
|
||||
MakeUnique<gfx::VRProcessChild>(*parentPID, messageChannelId);
|
||||
process = MakeUnique<gfx::VRProcessChild>(
|
||||
std::move(*clientChannel), *parentPID, messageChannelId);
|
||||
break;
|
||||
|
||||
case GeckoProcessType_RDD:
|
||||
process = MakeUnique<RDDProcessImpl>(*parentPID, messageChannelId);
|
||||
process = MakeUnique<RDDProcessImpl>(std::move(*clientChannel),
|
||||
*parentPID, messageChannelId);
|
||||
break;
|
||||
|
||||
case GeckoProcessType_Socket:
|
||||
ioInterposerGuard.Init();
|
||||
process =
|
||||
MakeUnique<net::SocketProcessImpl>(*parentPID, messageChannelId);
|
||||
process = MakeUnique<net::SocketProcessImpl>(
|
||||
std::move(*clientChannel), *parentPID, messageChannelId);
|
||||
break;
|
||||
|
||||
case GeckoProcessType_Utility:
|
||||
process =
|
||||
MakeUnique<ipc::UtilityProcessImpl>(*parentPID, messageChannelId);
|
||||
process = MakeUnique<ipc::UtilityProcessImpl>(
|
||||
std::move(*clientChannel), *parentPID, messageChannelId);
|
||||
break;
|
||||
|
||||
#if defined(MOZ_SANDBOX) && defined(XP_WIN)
|
||||
case GeckoProcessType_RemoteSandboxBroker:
|
||||
process = MakeUnique<RemoteSandboxBrokerProcessChild>(
|
||||
*parentPID, messageChannelId);
|
||||
std::move(*clientChannel), *parentPID, messageChannelId);
|
||||
break;
|
||||
#endif
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user