зеркало из https://github.com/mozilla/gecko-dev.git
Bug 771765 - Support template content process, part 2: IPC and glue changes. r=bent
Changes include: * Getting/resetting platform thread ID. * Creating an IPC channel with existing file descriptor sent from the template process. * Child process host with existing process forked from the template.
This commit is contained in:
Родитель
52df1fd957
Коммит
140b811282
|
@ -49,7 +49,11 @@ PlatformThreadId PlatformThread::CurrentId() {
|
|||
mach_port_deallocate(mach_task_self(), port);
|
||||
return port;
|
||||
#elif defined(OS_LINUX)
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
return (intptr_t) (pthread_self());
|
||||
#else
|
||||
return syscall(__NR_gettid);
|
||||
#endif
|
||||
#elif defined(OS_OPENBSD) || defined(__GLIBC__)
|
||||
return (intptr_t) (pthread_self());
|
||||
#elif defined(OS_NETBSD)
|
||||
|
|
|
@ -248,6 +248,9 @@ bool DidProcessCrash(bool* child_exited, ProcessHandle handle) {
|
|||
int status;
|
||||
const int result = HANDLE_EINTR(waitpid(handle, &status, WNOHANG));
|
||||
if (result == -1) {
|
||||
// The dead process originally spawned from Nuwa might be taken as not
|
||||
// crashed because the above waitpid() call returns -1 and ECHILD. The
|
||||
// caller shouldn't behave incorrectly because of this false negative.
|
||||
LOG(ERROR) << "waitpid failed pid:" << handle << " errno:" << errno;
|
||||
if (child_exited)
|
||||
*child_exited = false;
|
||||
|
|
|
@ -106,6 +106,12 @@ class Thread : PlatformThread::Delegate {
|
|||
// The thread ID.
|
||||
PlatformThreadId thread_id() const { return thread_id_; }
|
||||
|
||||
// Reset thread ID as current thread.
|
||||
PlatformThreadId reset_thread_id() {
|
||||
thread_id_ = PlatformThread::CurrentId();
|
||||
return thread_id_;
|
||||
}
|
||||
|
||||
// Returns true if the thread has been started, and not yet stopped.
|
||||
// When a thread is running, the thread_id_ is non-zero.
|
||||
bool IsRunning() const { return thread_id_ != 0; }
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include "base/waitable_event.h"
|
||||
#include "mozilla/ipc/ProcessChild.h"
|
||||
#include "mozilla/ipc/BrowserProcessSubThread.h"
|
||||
#include "mozilla/ipc/Transport.h"
|
||||
typedef mozilla::ipc::BrowserProcessSubThread ChromeThread;
|
||||
#include "chrome/common/ipc_logging.h"
|
||||
#include "chrome/common/notification_service.h"
|
||||
|
@ -19,6 +20,7 @@ typedef mozilla::ipc::BrowserProcessSubThread ChromeThread;
|
|||
#include "chrome/common/process_watcher.h"
|
||||
#include "chrome/common/result_codes.h"
|
||||
|
||||
using mozilla::ipc::FileDescriptor;
|
||||
|
||||
namespace {
|
||||
typedef std::list<ChildProcessHost*> ChildProcessList;
|
||||
|
@ -84,6 +86,22 @@ bool ChildProcessHost::CreateChannel() {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool ChildProcessHost::CreateChannel(FileDescriptor& aFileDescriptor) {
|
||||
if (channel_.get()) {
|
||||
channel_->Close();
|
||||
}
|
||||
channel_.reset(mozilla::ipc::OpenDescriptor(
|
||||
aFileDescriptor, IPC::Channel::MODE_SERVER));
|
||||
channel_->set_listener(&listener_);
|
||||
if (!channel_->Connect()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
opening_channel_ = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ChildProcessHost::SetHandle(base::ProcessHandle process) {
|
||||
#if defined(OS_WIN)
|
||||
process_event_.reset(new base::WaitableEvent(process));
|
||||
|
|
|
@ -15,6 +15,12 @@
|
|||
#include "chrome/common/child_process_info.h"
|
||||
#include "chrome/common/ipc_channel.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace ipc {
|
||||
class FileDescriptor;
|
||||
}
|
||||
}
|
||||
|
||||
class NotificationType;
|
||||
|
||||
// Plugins/workers and other child processes that live on the IO thread should
|
||||
|
@ -59,6 +65,8 @@ class ChildProcessHost :
|
|||
// Creates the IPC channel. Returns true iff it succeeded.
|
||||
bool CreateChannel();
|
||||
|
||||
bool CreateChannel(mozilla::ipc::FileDescriptor& aFileDescriptor);
|
||||
|
||||
// Once the subclass gets a handle to the process, it needs to tell
|
||||
// ChildProcessHost using this function.
|
||||
void SetHandle(base::ProcessHandle handle);
|
||||
|
|
|
@ -117,8 +117,11 @@ class Channel : public Message::Sender {
|
|||
// socketpair() in which case this method returns -1 for both parameters.
|
||||
void GetClientFileDescriptorMapping(int *src_fd, int *dest_fd) const;
|
||||
|
||||
// Return the server side of the socketpair.
|
||||
int GetServerFileDescriptor() const;
|
||||
// Return the file descriptor for communication with the peer.
|
||||
int GetFileDescriptor() const;
|
||||
|
||||
// Reset the file descriptor for communication with the peer.
|
||||
void ResetFileDescriptor(int fd);
|
||||
|
||||
// Close the client side of the socketpair.
|
||||
void CloseClientFileDescriptor();
|
||||
|
|
|
@ -356,6 +356,15 @@ bool Channel::ChannelImpl::CreatePipe(const std::wstring& channel_id,
|
|||
return EnqueueHelloMessage();
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the file descriptor for communication with the peer.
|
||||
*/
|
||||
void Channel::ChannelImpl::ResetFileDescriptor(int fd) {
|
||||
NS_ASSERTION(fd > 0 && fd == pipe_, "Invalid file descriptor");
|
||||
|
||||
EnqueueHelloMessage();
|
||||
}
|
||||
|
||||
bool Channel::ChannelImpl::EnqueueHelloMessage() {
|
||||
scoped_ptr<Message> msg(new Message(MSG_ROUTING_NONE,
|
||||
HELLO_MESSAGE_TYPE,
|
||||
|
@ -971,8 +980,12 @@ void Channel::GetClientFileDescriptorMapping(int *src_fd, int *dest_fd) const {
|
|||
return channel_impl_->GetClientFileDescriptorMapping(src_fd, dest_fd);
|
||||
}
|
||||
|
||||
int Channel::GetServerFileDescriptor() const {
|
||||
return channel_impl_->GetServerFileDescriptor();
|
||||
void Channel::ResetFileDescriptor(int fd) {
|
||||
channel_impl_->ResetFileDescriptor(fd);
|
||||
}
|
||||
|
||||
int Channel::GetFileDescriptor() const {
|
||||
return channel_impl_->GetFileDescriptor();
|
||||
}
|
||||
|
||||
void Channel::CloseClientFileDescriptor() {
|
||||
|
|
|
@ -36,8 +36,10 @@ class Channel::ChannelImpl : public MessageLoopForIO::Watcher {
|
|||
}
|
||||
bool Send(Message* message);
|
||||
void GetClientFileDescriptorMapping(int *src_fd, int *dest_fd) const;
|
||||
int GetServerFileDescriptor() const {
|
||||
DCHECK(mode_ == MODE_SERVER);
|
||||
|
||||
void ResetFileDescriptor(int fd);
|
||||
|
||||
int GetFileDescriptor() const {
|
||||
return pipe_;
|
||||
}
|
||||
void CloseClientFileDescriptor();
|
||||
|
|
|
@ -34,6 +34,10 @@
|
|||
#define NS_TASKBAR_CONTRACTID "@mozilla.org/windows-taskbar;1"
|
||||
#endif
|
||||
|
||||
#include "nsTArray.h"
|
||||
#include "nsClassHashtable.h"
|
||||
#include "nsHashKeys.h"
|
||||
|
||||
using mozilla::MonitorAutoLock;
|
||||
using mozilla::ipc::GeckoChildProcessHost;
|
||||
|
||||
|
@ -89,11 +93,6 @@ GeckoChildProcessHost::GeckoChildProcessHost(GeckoProcessType aProcessType,
|
|||
#endif
|
||||
{
|
||||
MOZ_COUNT_CTOR(GeckoChildProcessHost);
|
||||
|
||||
MessageLoop* ioLoop = XRE_GetIOMessageLoop();
|
||||
ioLoop->PostTask(FROM_HERE,
|
||||
NewRunnableMethod(this,
|
||||
&GeckoChildProcessHost::InitializeChannel));
|
||||
}
|
||||
|
||||
GeckoChildProcessHost::~GeckoChildProcessHost()
|
||||
|
@ -287,7 +286,7 @@ GeckoChildProcessHost::SyncLaunch(std::vector<std::string> aExtraOpts, int aTime
|
|||
|
||||
ioLoop->PostTask(FROM_HERE,
|
||||
NewRunnableMethod(this,
|
||||
&GeckoChildProcessHost::PerformAsyncLaunch,
|
||||
&GeckoChildProcessHost::RunPerformAsyncLaunch,
|
||||
aExtraOpts, arch));
|
||||
// NB: this uses a different mechanism than the chromium parent
|
||||
// class.
|
||||
|
@ -322,7 +321,7 @@ GeckoChildProcessHost::AsyncLaunch(std::vector<std::string> aExtraOpts)
|
|||
MessageLoop* ioLoop = XRE_GetIOMessageLoop();
|
||||
ioLoop->PostTask(FROM_HERE,
|
||||
NewRunnableMethod(this,
|
||||
&GeckoChildProcessHost::PerformAsyncLaunch,
|
||||
&GeckoChildProcessHost::RunPerformAsyncLaunch,
|
||||
aExtraOpts, base::GetCurrentProcessArchitecture()));
|
||||
|
||||
// This may look like the sync launch wait, but we only delay as
|
||||
|
@ -343,7 +342,7 @@ GeckoChildProcessHost::LaunchAndWaitForProcessHandle(StringVector aExtraOpts)
|
|||
MessageLoop* ioLoop = XRE_GetIOMessageLoop();
|
||||
ioLoop->PostTask(FROM_HERE,
|
||||
NewRunnableMethod(this,
|
||||
&GeckoChildProcessHost::PerformAsyncLaunch,
|
||||
&GeckoChildProcessHost::RunPerformAsyncLaunch,
|
||||
aExtraOpts, base::GetCurrentProcessArchitecture()));
|
||||
|
||||
MonitorAutoLock lock(mMonitor);
|
||||
|
@ -425,6 +424,14 @@ GeckoChildProcessHost::PerformAsyncLaunch(std::vector<std::string> aExtraOpts, b
|
|||
return retval;
|
||||
}
|
||||
|
||||
bool
|
||||
GeckoChildProcessHost::RunPerformAsyncLaunch(std::vector<std::string> aExtraOpts,
|
||||
base::ProcessArchitecture aArch)
|
||||
{
|
||||
InitializeChannel();
|
||||
return PerformAsyncLaunch(aExtraOpts, aArch);
|
||||
}
|
||||
|
||||
void
|
||||
#if defined(XP_WIN)
|
||||
AddAppDirToCommandLine(CommandLine& aCmdLine)
|
||||
|
@ -833,3 +840,52 @@ GeckoChildProcessHost::OnWaitableEventSignaled(base::WaitableEvent *event)
|
|||
}
|
||||
ChildProcessHost::OnWaitableEventSignaled(event);
|
||||
}
|
||||
|
||||
#ifdef MOZ_NUWA_PROCESS
|
||||
|
||||
using mozilla::ipc::GeckoExistingProcessHost;
|
||||
using mozilla::ipc::FileDescriptor;
|
||||
|
||||
GeckoExistingProcessHost::
|
||||
GeckoExistingProcessHost(GeckoProcessType aProcessType,
|
||||
base::ProcessHandle aProcess,
|
||||
const FileDescriptor& aFileDescriptor,
|
||||
ChildPrivileges aPrivileges)
|
||||
: GeckoChildProcessHost(aProcessType, aPrivileges)
|
||||
, mExistingProcessHandle(aProcess)
|
||||
, mExistingFileDescriptor(aFileDescriptor)
|
||||
{
|
||||
NS_ASSERTION(aFileDescriptor.IsValid(),
|
||||
"Expected file descriptor to be valid");
|
||||
}
|
||||
|
||||
GeckoExistingProcessHost::~GeckoExistingProcessHost()
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
GeckoExistingProcessHost::PerformAsyncLaunch(StringVector aExtraOpts,
|
||||
base::ProcessArchitecture aArch)
|
||||
{
|
||||
SetHandle(mExistingProcessHandle);
|
||||
|
||||
OpenPrivilegedHandle(base::GetProcId(mExistingProcessHandle));
|
||||
|
||||
MonitorAutoLock lock(mMonitor);
|
||||
mProcessState = PROCESS_CREATED;
|
||||
lock.Notify();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
GeckoExistingProcessHost::InitializeChannel()
|
||||
{
|
||||
CreateChannel(mExistingFileDescriptor);
|
||||
|
||||
MonitorAutoLock lock(mMonitor);
|
||||
mProcessState = CHANNEL_INITIALIZED;
|
||||
lock.Notify();
|
||||
}
|
||||
|
||||
#endif /* MOZ_NUWA_PROCESS */
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include "base/waitable_event.h"
|
||||
#include "chrome/common/child_process_host.h"
|
||||
|
||||
#include "mozilla/ipc/FileDescriptor.h"
|
||||
#include "mozilla/Monitor.h"
|
||||
|
||||
#include "nsXULAppAPI.h" // for GeckoProcessType
|
||||
|
@ -66,15 +67,15 @@ public:
|
|||
int32_t timeoutMs=0,
|
||||
base::ProcessArchitecture arch=base::GetCurrentProcessArchitecture());
|
||||
|
||||
bool PerformAsyncLaunch(StringVector aExtraOpts=StringVector(),
|
||||
base::ProcessArchitecture arch=base::GetCurrentProcessArchitecture());
|
||||
virtual bool PerformAsyncLaunch(StringVector aExtraOpts=StringVector(),
|
||||
base::ProcessArchitecture aArch=base::GetCurrentProcessArchitecture());
|
||||
|
||||
virtual void OnChannelConnected(int32_t peer_pid);
|
||||
virtual void OnMessageReceived(const IPC::Message& aMsg);
|
||||
virtual void OnChannelError();
|
||||
virtual void GetQueuedMessages(std::queue<IPC::Message>& queue);
|
||||
|
||||
void InitializeChannel();
|
||||
virtual void InitializeChannel();
|
||||
|
||||
virtual bool CanShutdown() { return true; }
|
||||
|
||||
|
@ -146,6 +147,8 @@ protected:
|
|||
task_t mChildTask;
|
||||
#endif
|
||||
|
||||
void OpenPrivilegedHandle(base::ProcessId aPid);
|
||||
|
||||
private:
|
||||
DISALLOW_EVIL_CONSTRUCTORS(GeckoChildProcessHost);
|
||||
|
||||
|
@ -153,7 +156,8 @@ private:
|
|||
bool PerformAsyncLaunchInternal(std::vector<std::string>& aExtraOpts,
|
||||
base::ProcessArchitecture arch);
|
||||
|
||||
void OpenPrivilegedHandle(base::ProcessId aPid);
|
||||
bool RunPerformAsyncLaunch(StringVector aExtraOpts=StringVector(),
|
||||
base::ProcessArchitecture aArch=base::GetCurrentProcessArchitecture());
|
||||
|
||||
// In between launching the subprocess and handing off its IPC
|
||||
// channel, there's a small window of time in which *we* might still
|
||||
|
@ -165,6 +169,28 @@ private:
|
|||
std::queue<IPC::Message> mQueue;
|
||||
};
|
||||
|
||||
#ifdef MOZ_NUWA_PROCESS
|
||||
class GeckoExistingProcessHost MOZ_FINAL : public GeckoChildProcessHost
|
||||
{
|
||||
public:
|
||||
GeckoExistingProcessHost(GeckoProcessType aProcessType,
|
||||
base::ProcessHandle aProcess,
|
||||
const FileDescriptor& aFileDescriptor,
|
||||
ChildPrivileges aPrivileges=base::PRIVILEGES_DEFAULT);
|
||||
|
||||
~GeckoExistingProcessHost();
|
||||
|
||||
virtual bool PerformAsyncLaunch(StringVector aExtraOpts=StringVector(),
|
||||
base::ProcessArchitecture aArch=base::GetCurrentProcessArchitecture()) MOZ_OVERRIDE;
|
||||
|
||||
virtual void InitializeChannel() MOZ_OVERRIDE;
|
||||
|
||||
private:
|
||||
base::ProcessHandle mExistingProcessHandle;
|
||||
mozilla::ipc::FileDescriptor mExistingFileDescriptor;
|
||||
};
|
||||
#endif /* MOZ_NUWA_PROCESS */
|
||||
|
||||
} /* namespace ipc */
|
||||
} /* namespace mozilla */
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@ CreateTransport(ProcessHandle /*unused*/, ProcessHandle /*unused*/,
|
|||
wstring id = ChildProcessInfo::GenerateRandomChannelID(aOne);
|
||||
// Use MODE_SERVER to force creation of the socketpair
|
||||
Transport t(id, Transport::MODE_SERVER, nullptr);
|
||||
int fd1 = t.GetServerFileDescriptor();
|
||||
int fd1 = t.GetFileDescriptor();
|
||||
int fd2, dontcare;
|
||||
t.GetClientFileDescriptorMapping(&fd2, &dontcare);
|
||||
if (fd1 < 0 || fd2 < 0) {
|
||||
|
|
Загрузка…
Ссылка в новой задаче