diff options
author | mdempsky@chromium.org <mdempsky@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-05-11 01:17:47 +0000 |
---|---|---|
committer | mdempsky@chromium.org <mdempsky@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-05-11 01:17:47 +0000 |
commit | 54ad01a07a6c2ffa6ee2d2ec11cd6d56b723cd5e (patch) | |
tree | ee8f209267515175b3c9c11a52c1fce9a699c675 /content/zygote | |
parent | 5cf28ab789a0fa2faf5050b8a60e296f25e808c6 (diff) | |
download | chromium_src-54ad01a07a6c2ffa6ee2d2ec11cd6d56b723cd5e.zip chromium_src-54ad01a07a6c2ffa6ee2d2ec11cd6d56b723cd5e.tar.gz chromium_src-54ad01a07a6c2ffa6ee2d2ec11cd6d56b723cd5e.tar.bz2 |
Add support for multiple zygote fork delegates
No functional changes yet, just preparation for splitting NaCl's fork
delegate into two different implementations.
BUG=364945
Review URL: https://codereview.chromium.org/269413004
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@269673 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content/zygote')
-rw-r--r-- | content/zygote/zygote_linux.cc | 61 | ||||
-rw-r--r-- | content/zygote/zygote_linux.h | 19 | ||||
-rw-r--r-- | content/zygote/zygote_main.h | 5 | ||||
-rw-r--r-- | content/zygote/zygote_main_linux.cc | 16 |
4 files changed, 49 insertions, 52 deletions
diff --git a/content/zygote/zygote_linux.cc b/content/zygote/zygote_linux.cc index 5f922a4..b518673 100644 --- a/content/zygote/zygote_linux.cc +++ b/content/zygote/zygote_linux.cc @@ -16,6 +16,7 @@ #include "base/linux_util.h" #include "base/logging.h" #include "base/macros.h" +#include "base/memory/scoped_vector.h" #include "base/pickle.h" #include "base/posix/eintr_wrapper.h" #include "base/posix/global_descriptors.h" @@ -57,8 +58,8 @@ void CreatePipe(base::ScopedFD* read_pipe, base::ScopedFD* write_pipe) { write_pipe->reset(raw_pipe[1]); } -void KillAndReap(pid_t pid, bool use_helper) { - if (use_helper) { +void KillAndReap(pid_t pid, ZygoteForkDelegate* helper) { + if (helper) { // Helper children may be forked in another PID namespace, so |pid| might // be meaningless to us; or we just might not be able to directly send it // signals. So we can't kill it. @@ -76,17 +77,10 @@ void KillAndReap(pid_t pid, bool use_helper) { } // namespace -Zygote::Zygote(int sandbox_flags, - ZygoteForkDelegate* helper) +Zygote::Zygote(int sandbox_flags, ScopedVector<ZygoteForkDelegate> helpers) : sandbox_flags_(sandbox_flags), - helper_(helper), - initial_uma_sample_(0), - initial_uma_boundary_value_(0) { - if (helper_) { - helper_->InitialUMA(&initial_uma_name_, - &initial_uma_sample_, - &initial_uma_boundary_value_); - } + helpers_(helpers.Pass()), + initial_uma_index_(0) { } Zygote::~Zygote() { @@ -265,9 +259,8 @@ bool Zygote::GetTerminationStatus(base::ProcessHandle real_pid, // We know about |real_pid|. const base::ProcessHandle child = child_info.internal_pid; if (child_info.started_from_helper) { - // Let the helper handle the request. - DCHECK(helper_); - if (!helper_->GetTerminationStatus(child, known_dead, status, exit_code)) { + if (!child_info.started_from_helper->GetTerminationStatus( + child, known_dead, status, exit_code)) { return false; } } else { @@ -330,14 +323,19 @@ int Zygote::ForkWithRealPid(const std::string& process_type, std::string* uma_name, int* uma_sample, int* uma_boundary_value) { - const bool use_helper = (helper_ && helper_->CanHelp(process_type, - uma_name, - uma_sample, - uma_boundary_value)); + ZygoteForkDelegate* helper = NULL; + for (ScopedVector<ZygoteForkDelegate>::iterator i = helpers_.begin(); + i != helpers_.end(); + ++i) { + if ((*i)->CanHelp(process_type, uma_name, uma_sample, uma_boundary_value)) { + helper = *i; + break; + } + } base::ScopedFD read_pipe, write_pipe; base::ProcessId pid = 0; - if (use_helper) { + if (helper) { int ipc_channel_fd = LookUpFd(fd_mapping, kPrimaryIPCChannel); if (ipc_channel_fd < 0) { DLOG(ERROR) << "Failed to find kPrimaryIPCChannel in FD mapping"; @@ -346,7 +344,7 @@ int Zygote::ForkWithRealPid(const std::string& process_type, std::vector<int> fds; fds.push_back(ipc_channel_fd); // kBrowserFDIndex fds.push_back(pid_oracle.get()); // kPIDOracleFDIndex - pid = helper_->Fork(process_type, fds, channel_id); + pid = helper->Fork(process_type, fds, channel_id); // Helpers should never return in the child process. CHECK_NE(pid, 0); @@ -416,16 +414,16 @@ int Zygote::ForkWithRealPid(const std::string& process_type, // If we successfully forked a child, but it crashed without sending // a message to the browser, the browser won't have found its PID. if (real_pid < 0) { - KillAndReap(pid, use_helper); + KillAndReap(pid, helper); return -1; } // If we're not using a helper, send the PID back to the child process. - if (!use_helper) { + if (!helper) { ssize_t written = HANDLE_EINTR(write(write_pipe.get(), &real_pid, sizeof(real_pid))); if (written != sizeof(real_pid)) { - KillAndReap(pid, use_helper); + KillAndReap(pid, helper); return -1; } } @@ -436,7 +434,7 @@ int Zygote::ForkWithRealPid(const std::string& process_type, NOTREACHED(); } process_info_map_[real_pid].internal_pid = pid; - process_info_map_[real_pid].started_from_helper = use_helper; + process_info_map_[real_pid].started_from_helper = helper; return real_pid; } @@ -538,14 +536,11 @@ bool Zygote::HandleForkRequest(int fd, pickle, iter, fds.Pass(), &uma_name, &uma_sample, &uma_boundary_value); if (child_pid == 0) return true; - if (uma_name.empty()) { - // There is no UMA report from this particular fork. - // Use the initial UMA report if any, and clear that record for next time. - // Note the swap method here is the efficient way to do this, since - // we know uma_name is empty. - uma_name.swap(initial_uma_name_); - uma_sample = initial_uma_sample_; - uma_boundary_value = initial_uma_boundary_value_; + // If there's no UMA report for this particular fork, then check if any + // helpers have an initial UMA report for us to send instead. + while (uma_name.empty() && initial_uma_index_ < helpers_.size()) { + helpers_[initial_uma_index_++]->InitialUMA( + &uma_name, &uma_sample, &uma_boundary_value); } // Must always send reply, as ZygoteHost blocks while waiting for it. Pickle reply_pickle; diff --git a/content/zygote/zygote_linux.h b/content/zygote/zygote_linux.h index 8e1996c..ef7e071 100644 --- a/content/zygote/zygote_linux.h +++ b/content/zygote/zygote_linux.h @@ -5,6 +5,8 @@ #ifndef CONTENT_ZYGOTE_ZYGOTE_H_ #define CONTENT_ZYGOTE_ZYGOTE_H_ +#include <stddef.h> + #include <string> #include "base/containers/small_map.h" @@ -26,8 +28,7 @@ class ZygoteForkDelegate; // runs it. class Zygote { public: - Zygote(int sandbox_flags, - ZygoteForkDelegate* helper); + Zygote(int sandbox_flags, ScopedVector<ZygoteForkDelegate> helpers); ~Zygote(); bool ProcessRequests(); @@ -36,9 +37,8 @@ class Zygote { struct ZygoteProcessInfo { // Pid from inside the Zygote's PID namespace. base::ProcessHandle internal_pid; - // Keeps track of whether or not a process was started from a fork - // delegate helper. - bool started_from_helper; + // Keeps track of which fork delegate helper the process was started from. + ZygoteForkDelegate* started_from_helper; }; typedef base::SmallMap< std::map<base::ProcessHandle, ZygoteProcessInfo> > ZygoteProcessMap; @@ -119,13 +119,10 @@ class Zygote { ZygoteProcessMap process_info_map_; const int sandbox_flags_; - ZygoteForkDelegate* helper_; + ScopedVector<ZygoteForkDelegate> helpers_; - // These might be set by helper_->InitialUMA. They supply a UMA enumeration - // sample we should report on the first fork. - std::string initial_uma_name_; - int initial_uma_sample_; - int initial_uma_boundary_value_; + // Count of how many fork delegates for which we've invoked InitialUMA(). + size_t initial_uma_index_; }; } // namespace content diff --git a/content/zygote/zygote_main.h b/content/zygote/zygote_main.h index 6470232..119210f 100644 --- a/content/zygote/zygote_main.h +++ b/content/zygote/zygote_main.h @@ -5,13 +5,16 @@ #ifndef CONTENT_ZYGOTE_ZYGOTE_MAIN_H_ #define CONTENT_ZYGOTE_ZYGOTE_MAIN_H_ +template <typename> +class ScopedVector; + namespace content { struct MainFunctionParams; class ZygoteForkDelegate; bool ZygoteMain(const MainFunctionParams& params, - ZygoteForkDelegate* forkdelegate); + ScopedVector<ZygoteForkDelegate> fork_delegates); } // namespace content diff --git a/content/zygote/zygote_main_linux.cc b/content/zygote/zygote_main_linux.cc index 11f0602..1232969 100644 --- a/content/zygote/zygote_main_linux.cc +++ b/content/zygote/zygote_main_linux.cc @@ -21,6 +21,7 @@ #include "base/command_line.h" #include "base/compiler_specific.h" #include "base/linux_util.h" +#include "base/memory/scoped_vector.h" #include "base/native_library.h" #include "base/pickle.h" #include "base/posix/eintr_wrapper.h" @@ -442,7 +443,7 @@ static void EnterLayerOneSandbox(LinuxSandbox* linux_sandbox, } bool ZygoteMain(const MainFunctionParams& params, - ZygoteForkDelegate* forkdelegate) { + ScopedVector<ZygoteForkDelegate> fork_delegates) { g_am_zygote_or_renderer = true; sandbox::InitLibcUrandomOverrides(); @@ -462,11 +463,12 @@ bool ZygoteMain(const MainFunctionParams& params, std::vector<int>())); } - if (forkdelegate != NULL) { - VLOG(1) << "ZygoteMain: initializing fork delegate"; - forkdelegate->Init(GetSandboxFD(), must_enable_setuid_sandbox); - } else { - VLOG(1) << "ZygoteMain: fork delegate is NULL"; + VLOG(1) << "ZygoteMain: initializing " << fork_delegates.size() + << " fork delegates"; + for (ScopedVector<ZygoteForkDelegate>::iterator i = fork_delegates.begin(); + i != fork_delegates.end(); + ++i) { + (*i)->Init(GetSandboxFD(), must_enable_setuid_sandbox); } // Turn on the first layer of the sandbox if the configuration warrants it. @@ -476,7 +478,7 @@ bool ZygoteMain(const MainFunctionParams& params, bool setuid_sandbox_engaged = sandbox_flags & kSandboxLinuxSUID; CHECK_EQ(must_enable_setuid_sandbox, setuid_sandbox_engaged); - Zygote zygote(sandbox_flags, forkdelegate); + Zygote zygote(sandbox_flags, fork_delegates.Pass()); // This function call can return multiple times, once per fork(). return zygote.ProcessRequests(); } |