Index: content/zygote/zygote_linux.cc |
diff --git a/content/zygote/zygote_linux.cc b/content/zygote/zygote_linux.cc |
index 5f922a4d662790d72c3a6b9e8d0de3d9a739fbd8..b5186734de8ef82449bec27c0c9a12e90a0d24ec 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; |