Enable zygote manager by default.

Fix broken recursion check.
Make OpenFile warning less scary, indicate it's normal at start of ui tests.
Make ui tests pass.
Avoid generating extra code on Mac.

BUG=11841
TEST=start the browser, then make chrome and all .pak files unreadable; or alternately, start an installed browser, and uninstall the browser while it's running.  Then create a new tab and browse to two new sites. 

Review URL: http://codereview.chromium.org/119289

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@17909 0039d316-1c4b-4281-b951-d872f2087c98
Esse commit está contido em:
dkegel@google.com
2009-06-08 23:29:11 +00:00
commit 0f89d1ee85
8 arquivos alterados com 107 adições e 19 exclusões
+1 -1
Ver Arquivo
@@ -633,7 +633,7 @@ bool MemoryMappedFile::MapFileToMemory(const FilePath& file_name) {
file_ = zm->OpenFile(file_name.value().c_str());
if (file_ == -1) {
LOG(INFO) << "Zygote manager can't open " << file_name.value()
<< ", retrying locally";
<< ", retrying locally. (OK at start of ui_tests.)";
}
}
#endif // defined(OS_LINUX)
+5 -1
Ver Arquivo
@@ -208,7 +208,7 @@ bool InitializeLogFileHandle() {
}
}
SetFilePointer(log_file, 0, 0, FILE_END);
#elif defined(OS_POSIX)
#elif defined(OS_LINUX)
// Reserve global fd slots.
int reserved_fds[kReservedFds];
for (int i=0; i < kReservedFds; i++)
@@ -220,6 +220,10 @@ bool InitializeLogFileHandle() {
for (int i=0; i < kReservedFds; i++)
close(reserved_fds[i]);
if (log_file == NULL)
return false;
#elif defined(OS_POSIX)
log_file = fopen(log_file_name->c_str(), "a");
if (log_file == NULL)
return false;
#endif
+9
Ver Arquivo
@@ -23,6 +23,7 @@
#include <vector>
#include "base/command_line.h"
#include "base/file_path.h"
#include "base/process.h"
#if defined(OS_WIN)
@@ -87,6 +88,14 @@ void CloseProcessHandle(ProcessHandle process);
// Win XP SP1 as well.
ProcessId GetProcId(ProcessHandle process);
#if defined(OS_LINUX)
// Returns the ID for the parent of the given process.
ProcessId GetParentProcessId(ProcessHandle process);
// Returns the path to the executable of the given process.
FilePath GetProcessExecutablePath(ProcessHandle process);
#endif
#if defined(OS_POSIX)
// Sets all file descriptors to close on exec except for stdin, stdout
// and stderr.
+45 -1
Ver Arquivo
@@ -7,10 +7,10 @@
#include <ctype.h>
#include <dirent.h>
#include <fcntl.h>
#include <unistd.h>
#include <string>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include "base/eintr_wrapper.h"
#include "base/file_util.h"
@@ -42,6 +42,50 @@ void GetProcStats(pid_t pid, std::vector<std::string>* proc_stats) {
namespace base {
ProcessId GetParentProcessId(ProcessHandle process) {
FilePath stat_file("/proc");
stat_file = stat_file.Append(IntToString(process));
stat_file = stat_file.Append("status");
std::string status;
if (!file_util::ReadFileToString(stat_file, &status))
return -1;
StringTokenizer tokenizer(status, ":\n");
ParsingState state = KEY_NAME;
std::string last_key_name;
while (tokenizer.GetNext()) {
switch (state) {
case KEY_NAME:
last_key_name = tokenizer.token();
state = KEY_VALUE;
break;
case KEY_VALUE:
DCHECK(!last_key_name.empty());
if (last_key_name == "PPid") {
pid_t ppid = StringToInt(tokenizer.token());
return ppid;
}
state = KEY_NAME;
break;
}
}
NOTREACHED();
return -1;
}
FilePath GetProcessExecutablePath(ProcessHandle process) {
FilePath stat_file("/proc");
stat_file = stat_file.Append(IntToString(process));
stat_file = stat_file.Append("exe");
char exename[2048];
ssize_t len = readlink(stat_file.value().c_str(), exename, sizeof(exename));
if (len < 1) {
// No such process. Happens frequently in e.g. TerminateAllChromeProcesses
return FilePath();
}
return FilePath(std::string(exename, len));
}
bool ForkApp(const std::vector<std::string>& argv,
const file_handle_mapping_vector& fds_to_remap,
ProcessHandle* process_handle) {
+7
Ver Arquivo
@@ -270,6 +270,13 @@ TEST_F(ProcessUtilTest, GetAppOutput) {
EXPECT_STREQ("foobar42", output.c_str());
}
#if defined(OS_LINUX)
TEST_F(ProcessUtilTest, GetParentProcessId) {
base::ProcessId ppid = GetParentProcessId(GetCurrentProcId());
EXPECT_EQ(ppid, getppid());
}
#endif
#endif // defined(OS_POSIX)
} // namespace base
+17 -13
Ver Arquivo
@@ -54,6 +54,12 @@ ZygoteManager::~ZygoteManager() {
close(canary_fd_);
canary_fd_ = -1;
}
#ifndef OFFICIAL_BUILD
// Closing the canary kills the server,
// so after this it's ok for e.g. unit tests
// to start a new zygote server.
(void) unsetenv("ZYGOTE_MANAGER_STARTED");
#endif
}
// Runs in client process
@@ -61,13 +67,7 @@ ZygoteManager* ZygoteManager::Get() {
static bool checked = false;
static bool enabled = false;
if (!checked) {
enabled = (getenv("ENABLE_ZYGOTE_MANAGER") != NULL);
// sanity check - make sure all the places that relaunch chrome
// have been zygotified.
if (enabled)
DCHECK(getenv("ZYGOTE_MANAGER_STARTED") == NULL)
<< "fork/exec used instead of LongFork";
(void) setenv("ZYGOTE_MANAGER_STARTED", "1", 1);
enabled = (getenv("DISABLE_ZYGOTE_MANAGER") == NULL);
checked = true;
}
if (!enabled)
@@ -594,7 +594,6 @@ bool ZygoteManager::ReadAndHandleMessage(std::vector<std::string>** newargv) {
if (nactive == -1) {
if (errno == EINTR) {
LOG(INFO) << "poll interrupted";
// Probably SIGCHLD. Return to main loop so it can reap.
return true;
}
@@ -723,6 +722,12 @@ std::vector<std::string>* ZygoteManager::Start() {
DCHECK(server_fd_ == -1);
DCHECK(client_fd_ == -1);
#ifndef OFFICIAL_BUILD
// Disallow nested ZygoteManager servers
CHECK(getenv("ZYGOTE_MANAGER_STARTED") == NULL) << "already started?!";
(void) setenv("ZYGOTE_MANAGER_STARTED", "1", 1);
#endif
int pipe_fds[2];
// Avoid using the reserved fd slots.
@@ -761,11 +766,11 @@ std::vector<std::string>* ZygoteManager::Start() {
// Fork a fork server.
pid_t childpid = fork();
if (childpid) {
if (!childpid) {
for (int i=0; i < kReservedFds; i++)
close(reserved_fds[i]);
// Original parent. Continues on with the main program
// Original child. Continues on with the main program
// and becomes the first client.
close(server_fd_);
server_fd_ = -1;
@@ -789,7 +794,7 @@ std::vector<std::string>* ZygoteManager::Start() {
action.sa_handler = SIGCHLDHandler;
CHECK(sigaction(SIGCHLD, &action, NULL) == 0);
// Original child. Acts as the server.
// Original process. Acts as the server.
while (true) {
std::vector<std::string>* newargv = NULL;
if (!ReadAndHandleMessage(&newargv))
@@ -812,7 +817,6 @@ std::vector<std::string>* ZygoteManager::Start() {
}
}
// Server cleanup after EOF or error reading from the socket.
// Chrome doesn't seem to get here in practice.
Delete(FilePath(lockfile_), false);
// TODO(dkegel): real error handling
LOG(INFO) << "exiting. " << cached_fds_.size() << " cached fds.";
@@ -821,7 +825,7 @@ std::vector<std::string>* ZygoteManager::Start() {
LOG(INFO) << "Closing fd " << i->second << " filename " << i->first;
close(i->second);
}
exit(-1);
exit(0);
}
}
}
+2 -2
Ver Arquivo
@@ -29,8 +29,8 @@ class ZygoteManager {
// The normal way to get a ZygoteManager is via this singleton factory.
static ZygoteManager* Get();
ZygoteManager() : server_fd_(-1), client_fd_(-1), canary_fd_(-1),
lockfd_(-1) {
ZygoteManager() :
server_fd_(-1), client_fd_(-1), canary_fd_(-1), lockfd_(-1) {
}
~ZygoteManager();
+21 -1
Ver Arquivo
@@ -77,13 +77,33 @@ ChromeProcessList GetRunningChromeProcesses(const FilePath& data_dir) {
if (browser_pid < 0)
return result;
ChromeProcessFilter filter(browser_pid);
// Normally, the browser is the parent process for all the renderers
base::ProcessId parent_pid = browser_pid;
#if defined(OS_LINUX)
// But if the browser's parent is the same executable as the browser,
// then it's the zygote manager, and it's the parent for all the renderers.
base::ProcessId manager_pid = base::GetParentProcessId(browser_pid);
FilePath selfPath = base::GetProcessExecutablePath(browser_pid);
FilePath managerPath = base::GetProcessExecutablePath(manager_pid);
if (!selfPath.empty() && !managerPath.empty() && selfPath == managerPath) {
LOG(INFO) << "Zygote manager in use.";
parent_pid = manager_pid;
}
#endif
ChromeProcessFilter filter(parent_pid);
base::NamedProcessIterator it(chrome::kBrowserProcessExecutableName, &filter);
const ProcessEntry* process_entry;
while ((process_entry = it.NextProcessEntry())) {
#if defined(OS_WIN)
result.push_back(process_entry->th32ProcessID);
#elif defined(OS_LINUX)
// Don't count the zygote manager, that screws up unit tests,
// and it will exit cleanly on its own when first client exits.
if (process_entry->pid != manager_pid)
result.push_back(process_entry->pid);
#elif defined(OS_POSIX)
result.push_back(process_entry->pid);
#endif