OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "content/browser/zygote_host_linux.h" | 5 #include "content/browser/zygote_host_impl_linux.h" |
6 | 6 |
7 #include <sys/socket.h> | 7 #include <sys/socket.h> |
8 #include <sys/stat.h> | 8 #include <sys/stat.h> |
9 #include <sys/types.h> | 9 #include <sys/types.h> |
10 #include <unistd.h> | 10 #include <unistd.h> |
11 | 11 |
12 #include "base/base_switches.h" | 12 #include "base/base_switches.h" |
13 #include "base/command_line.h" | 13 #include "base/command_line.h" |
14 #include "base/eintr_wrapper.h" | 14 #include "base/eintr_wrapper.h" |
15 #include "base/environment.h" | 15 #include "base/environment.h" |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
51 std::string value; | 51 std::string value; |
52 if (env->GetVar(envvar, &value)) | 52 if (env->GetVar(envvar, &value)) |
53 env->SetVar(saved_envvar, value); | 53 env->SetVar(saved_envvar, value); |
54 else | 54 else |
55 env->UnSetVar(saved_envvar); | 55 env->UnSetVar(saved_envvar); |
56 | 56 |
57 free(saved_envvar); | 57 free(saved_envvar); |
58 } | 58 } |
59 } | 59 } |
60 | 60 |
61 ZygoteHost::ZygoteHost() | 61 // static |
| 62 content::ZygoteHost* content::ZygoteHost::GetInstance() { |
| 63 return ZygoteHostImpl::GetInstance(); |
| 64 } |
| 65 |
| 66 ZygoteHostImpl::ZygoteHostImpl() |
62 : control_fd_(-1), | 67 : control_fd_(-1), |
63 pid_(-1), | 68 pid_(-1), |
64 init_(false), | 69 init_(false), |
65 using_suid_sandbox_(false), | 70 using_suid_sandbox_(false), |
66 have_read_sandbox_status_word_(false), | 71 have_read_sandbox_status_word_(false), |
67 sandbox_status_(0) {} | 72 sandbox_status_(0) {} |
68 | 73 |
69 ZygoteHost::~ZygoteHost() { | 74 ZygoteHostImpl::~ZygoteHostImpl() { |
70 if (init_) | 75 if (init_) |
71 close(control_fd_); | 76 close(control_fd_); |
72 } | 77 } |
73 | 78 |
74 // static | 79 // static |
75 ZygoteHost* ZygoteHost::GetInstance() { | 80 ZygoteHostImpl* ZygoteHostImpl::GetInstance() { |
76 return Singleton<ZygoteHost>::get(); | 81 return Singleton<ZygoteHostImpl>::get(); |
77 } | 82 } |
78 | 83 |
79 void ZygoteHost::Init(const std::string& sandbox_cmd) { | 84 void ZygoteHostImpl::Init(const std::string& sandbox_cmd) { |
80 DCHECK(!init_); | 85 DCHECK(!init_); |
81 init_ = true; | 86 init_ = true; |
82 | 87 |
83 FilePath chrome_path; | 88 FilePath chrome_path; |
84 CHECK(PathService::Get(base::FILE_EXE, &chrome_path)); | 89 CHECK(PathService::Get(base::FILE_EXE, &chrome_path)); |
85 CommandLine cmd_line(chrome_path); | 90 CommandLine cmd_line(chrome_path); |
86 | 91 |
87 cmd_line.AppendSwitchASCII(switches::kProcessType, switches::kZygoteProcess); | 92 cmd_line.AppendSwitchASCII(switches::kProcessType, switches::kZygoteProcess); |
88 | 93 |
89 int fds[2]; | 94 int fds[2]; |
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
214 | 219 |
215 Pickle pickle; | 220 Pickle pickle; |
216 pickle.WriteInt(kCmdGetSandboxStatus); | 221 pickle.WriteInt(kCmdGetSandboxStatus); |
217 std::vector<int> empty_fds; | 222 std::vector<int> empty_fds; |
218 if (!UnixDomainSocket::SendMsg(control_fd_, pickle.data(), pickle.size(), | 223 if (!UnixDomainSocket::SendMsg(control_fd_, pickle.data(), pickle.size(), |
219 empty_fds)) | 224 empty_fds)) |
220 LOG(FATAL) << "Cannot communicate with zygote"; | 225 LOG(FATAL) << "Cannot communicate with zygote"; |
221 // We don't wait for the reply. We'll read it in ReadReply. | 226 // We don't wait for the reply. We'll read it in ReadReply. |
222 } | 227 } |
223 | 228 |
224 ssize_t ZygoteHost::ReadReply(void* buf, size_t buf_len) { | 229 ssize_t ZygoteHostImpl::ReadReply(void* buf, size_t buf_len) { |
225 // At startup we send a kCmdGetSandboxStatus request to the zygote, but don't | 230 // At startup we send a kCmdGetSandboxStatus request to the zygote, but don't |
226 // wait for the reply. Thus, the first time that we read from the zygote, we | 231 // wait for the reply. Thus, the first time that we read from the zygote, we |
227 // get the reply to that request. | 232 // get the reply to that request. |
228 if (!have_read_sandbox_status_word_) { | 233 if (!have_read_sandbox_status_word_) { |
229 if (HANDLE_EINTR(read(control_fd_, &sandbox_status_, | 234 if (HANDLE_EINTR(read(control_fd_, &sandbox_status_, |
230 sizeof(sandbox_status_))) != | 235 sizeof(sandbox_status_))) != |
231 sizeof(sandbox_status_)) { | 236 sizeof(sandbox_status_)) { |
232 return -1; | 237 return -1; |
233 } | 238 } |
234 have_read_sandbox_status_word_ = true; | 239 have_read_sandbox_status_word_ = true; |
235 } | 240 } |
236 | 241 |
237 return HANDLE_EINTR(read(control_fd_, buf, buf_len)); | 242 return HANDLE_EINTR(read(control_fd_, buf, buf_len)); |
238 } | 243 } |
239 | 244 |
240 pid_t ZygoteHost::ForkRequest( | 245 pid_t ZygoteHostImpl::ForkRequest( |
241 const std::vector<std::string>& argv, | 246 const std::vector<std::string>& argv, |
242 const base::GlobalDescriptors::Mapping& mapping, | 247 const base::GlobalDescriptors::Mapping& mapping, |
243 const std::string& process_type) { | 248 const std::string& process_type) { |
244 DCHECK(init_); | 249 DCHECK(init_); |
245 Pickle pickle; | 250 Pickle pickle; |
246 | 251 |
247 pickle.WriteInt(kCmdFork); | 252 pickle.WriteInt(kCmdFork); |
248 pickle.WriteString(process_type); | 253 pickle.WriteString(process_type); |
249 pickle.WriteInt(argv.size()); | 254 pickle.WriteInt(argv.size()); |
250 for (std::vector<std::string>::const_iterator | 255 for (std::vector<std::string>::const_iterator |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
312 // chrome::kLowestRendererOomScore in chrome/chrome_constants.h, but | 317 // chrome::kLowestRendererOomScore in chrome/chrome_constants.h, but |
313 // that's not something we can include here.) | 318 // that's not something we can include here.) |
314 const int kLowestRendererOomScore = 300; | 319 const int kLowestRendererOomScore = 300; |
315 AdjustRendererOOMScore(pid, kLowestRendererOomScore); | 320 AdjustRendererOOMScore(pid, kLowestRendererOomScore); |
316 #endif | 321 #endif |
317 | 322 |
318 return pid; | 323 return pid; |
319 } | 324 } |
320 | 325 |
321 #if !defined(OS_OPENBSD) | 326 #if !defined(OS_OPENBSD) |
322 void ZygoteHost::AdjustRendererOOMScore(base::ProcessHandle pid, int score) { | 327 void ZygoteHostImpl::AdjustRendererOOMScore(base::ProcessHandle pid, |
| 328 int score) { |
323 // 1) You can't change the oom_score_adj of a non-dumpable process | 329 // 1) You can't change the oom_score_adj of a non-dumpable process |
324 // (EPERM) unless you're root. Because of this, we can't set the | 330 // (EPERM) unless you're root. Because of this, we can't set the |
325 // oom_adj from the browser process. | 331 // oom_adj from the browser process. |
326 // | 332 // |
327 // 2) We can't set the oom_score_adj before entering the sandbox | 333 // 2) We can't set the oom_score_adj before entering the sandbox |
328 // because the zygote is in the sandbox and the zygote is as | 334 // because the zygote is in the sandbox and the zygote is as |
329 // critical as the browser process. Its oom_adj value shouldn't | 335 // critical as the browser process. Its oom_adj value shouldn't |
330 // be changed. | 336 // be changed. |
331 // | 337 // |
332 // 3) A non-dumpable process can't even change its own oom_score_adj | 338 // 3) A non-dumpable process can't even change its own oom_score_adj |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
380 &sandbox_helper_process)) { | 386 &sandbox_helper_process)) { |
381 base::EnsureProcessGetsReaped(sandbox_helper_process); | 387 base::EnsureProcessGetsReaped(sandbox_helper_process); |
382 } | 388 } |
383 } else if (!using_suid_sandbox_) { | 389 } else if (!using_suid_sandbox_) { |
384 if (!base::AdjustOOMScore(pid, score)) | 390 if (!base::AdjustOOMScore(pid, score)) |
385 PLOG(ERROR) << "Failed to adjust OOM score of renderer with pid " << pid; | 391 PLOG(ERROR) << "Failed to adjust OOM score of renderer with pid " << pid; |
386 } | 392 } |
387 } | 393 } |
388 #endif | 394 #endif |
389 | 395 |
390 void ZygoteHost::EnsureProcessTerminated(pid_t process) { | 396 void ZygoteHostImpl::EnsureProcessTerminated(pid_t process) { |
391 DCHECK(init_); | 397 DCHECK(init_); |
392 Pickle pickle; | 398 Pickle pickle; |
393 | 399 |
394 pickle.WriteInt(kCmdReap); | 400 pickle.WriteInt(kCmdReap); |
395 pickle.WriteInt(process); | 401 pickle.WriteInt(process); |
396 | 402 |
397 if (HANDLE_EINTR(write(control_fd_, pickle.data(), pickle.size())) < 0) | 403 if (HANDLE_EINTR(write(control_fd_, pickle.data(), pickle.size())) < 0) |
398 PLOG(ERROR) << "write"; | 404 PLOG(ERROR) << "write"; |
399 } | 405 } |
400 | 406 |
401 base::TerminationStatus ZygoteHost::GetTerminationStatus( | 407 base::TerminationStatus ZygoteHostImpl::GetTerminationStatus( |
402 base::ProcessHandle handle, | 408 base::ProcessHandle handle, |
403 int* exit_code) { | 409 int* exit_code) { |
404 DCHECK(init_); | 410 DCHECK(init_); |
405 Pickle pickle; | 411 Pickle pickle; |
406 pickle.WriteInt(kCmdGetTerminationStatus); | 412 pickle.WriteInt(kCmdGetTerminationStatus); |
407 pickle.WriteInt(handle); | 413 pickle.WriteInt(handle); |
408 | 414 |
409 // Set this now to handle the early termination cases. | 415 // Set this now to handle the early termination cases. |
410 if (exit_code) | 416 if (exit_code) |
411 *exit_code = content::RESULT_CODE_NORMAL_EXIT; | 417 *exit_code = content::RESULT_CODE_NORMAL_EXIT; |
(...skipping 24 matching lines...) Expand all Loading... |
436 !read_pickle.ReadInt(&iter, &tmp_exit_code)) { | 442 !read_pickle.ReadInt(&iter, &tmp_exit_code)) { |
437 LOG(WARNING) << "Error parsing GetTerminationStatus response from zygote."; | 443 LOG(WARNING) << "Error parsing GetTerminationStatus response from zygote."; |
438 return base::TERMINATION_STATUS_NORMAL_TERMINATION; | 444 return base::TERMINATION_STATUS_NORMAL_TERMINATION; |
439 } | 445 } |
440 | 446 |
441 if (exit_code) | 447 if (exit_code) |
442 *exit_code = tmp_exit_code; | 448 *exit_code = tmp_exit_code; |
443 | 449 |
444 return static_cast<base::TerminationStatus>(status); | 450 return static_cast<base::TerminationStatus>(status); |
445 } | 451 } |
| 452 |
| 453 pid_t ZygoteHostImpl::GetPid() const { |
| 454 return pid_; |
| 455 } |
| 456 |
| 457 int ZygoteHostImpl::GetSandboxStatus() const { |
| 458 if (have_read_sandbox_status_word_) |
| 459 return sandbox_status_; |
| 460 return 0; |
| 461 } |
OLD | NEW |