Chromium Code Reviews| 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/child_process_launcher.h" | 5 #include "content/browser/child_process_launcher.h" |
| 6 | 6 |
| 7 #include <utility> // For std::pair. | 7 #include <utility> // For std::pair. |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 71 // |this_object| is NOT thread safe. Only use it to post a task back. | 71 // |this_object| is NOT thread safe. Only use it to post a task back. |
| 72 scoped_refptr<Context> this_object, | 72 scoped_refptr<Context> this_object, |
| 73 BrowserThread::ID client_thread_id, | 73 BrowserThread::ID client_thread_id, |
| 74 const base::TimeTicks begin_launch_time, | 74 const base::TimeTicks begin_launch_time, |
| 75 base::ProcessHandle handle); | 75 base::ProcessHandle handle); |
| 76 #endif | 76 #endif |
| 77 | 77 |
| 78 // Resets the client (the client is going away). | 78 // Resets the client (the client is going away). |
| 79 void ResetClient(); | 79 void ResetClient(); |
| 80 | 80 |
| 81 bool IsStarting() const { return starting_; } | |
|
Charlie Reis
2014/11/20 18:00:09
nit: is_starting()
rvargas (doing something else)
2014/11/20 22:36:14
Done.
| |
| 82 | |
| 83 const base::Process& GetProcess() const { return process_; } | |
|
Charlie Reis
2014/11/20 18:00:09
nit: process()
rvargas (doing something else)
2014/11/20 22:36:14
Done.
| |
| 84 | |
| 85 int exit_code() const { return exit_code_; } | |
| 86 | |
| 87 base::TerminationStatus termination_status() const { | |
| 88 return termination_status_; | |
| 89 } | |
| 90 | |
| 81 void set_terminate_child_on_shutdown(bool terminate_on_shutdown) { | 91 void set_terminate_child_on_shutdown(bool terminate_on_shutdown) { |
| 82 terminate_child_on_shutdown_ = terminate_on_shutdown; | 92 terminate_child_on_shutdown_ = terminate_on_shutdown; |
| 83 } | 93 } |
| 84 | 94 |
| 85 void GetTerminationStatus() { | 95 void UpdateTerminationStatus(bool known_dead); |
| 86 termination_status_ = | 96 |
| 87 base::GetTerminationStatus(process_.Handle(), &exit_code_); | 97 void Close() { process_.Close(); } |
|
Charlie Reis
2014/11/20 18:00:09
Minor nit: Perhaps this should not be defined inli
rvargas (doing something else)
2014/11/20 22:36:14
It is not defined inline to signal it is fast or t
| |
| 88 } | |
| 89 | 98 |
| 90 void SetProcessBackgrounded(bool background); | 99 void SetProcessBackgrounded(bool background); |
| 91 | 100 |
| 92 private: | 101 private: |
| 93 friend class base::RefCountedThreadSafe<ChildProcessLauncher::Context>; | 102 friend class base::RefCountedThreadSafe<ChildProcessLauncher::Context>; |
| 94 friend class ChildProcessLauncher; | |
| 95 | 103 |
| 96 ~Context() { | 104 ~Context() { |
| 97 Terminate(); | 105 Terminate(); |
| 98 } | 106 } |
| 99 | 107 |
| 100 static void RecordHistograms(base::TimeTicks begin_launch_time); | 108 static void RecordHistograms(base::TimeTicks begin_launch_time); |
| 101 static void RecordLaunchHistograms(base::TimeDelta launch_time); | 109 static void RecordLaunchHistograms(base::TimeDelta launch_time); |
| 102 | 110 |
| 103 // Performs the actual work of launching the process. | 111 // Performs the actual work of launching the process. |
| 104 // Runs on the PROCESS_LAUNCHER thread. | 112 // Runs on the PROCESS_LAUNCHER thread. |
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 211 } | 219 } |
| 212 #endif | 220 #endif |
| 213 | 221 |
| 214 void ChildProcessLauncher::Context::ResetClient() { | 222 void ChildProcessLauncher::Context::ResetClient() { |
| 215 // No need for locking as this function gets called on the same thread that | 223 // No need for locking as this function gets called on the same thread that |
| 216 // client_ would be used. | 224 // client_ would be used. |
| 217 CHECK(BrowserThread::CurrentlyOn(client_thread_id_)); | 225 CHECK(BrowserThread::CurrentlyOn(client_thread_id_)); |
| 218 client_ = NULL; | 226 client_ = NULL; |
| 219 } | 227 } |
| 220 | 228 |
| 229 void ChildProcessLauncher::Context::UpdateTerminationStatus(bool known_dead) { | |
| 230 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID) | |
| 231 if (zygote_) { | |
| 232 termination_status_ = ZygoteHostImpl::GetInstance()-> | |
| 233 GetTerminationStatus(process_.Handle(), known_dead, &exit_code_); | |
| 234 } else if (known_dead) { | |
| 235 termination_status_ = | |
| 236 base::GetKnownDeadTerminationStatus(process_.Handle(), &exit_code_); | |
| 237 } else { | |
| 238 #elif defined(OS_MACOSX) | |
| 239 if (known_dead) { | |
| 240 termination_status_ = | |
| 241 base::GetKnownDeadTerminationStatus(process_.Handle(), &exit_code_); | |
| 242 } else { | |
| 243 #elif defined(OS_ANDROID) | |
| 244 if (IsChildProcessOomProtected(process_.Handle())) { | |
| 245 termination_status_ = base::TERMINATION_STATUS_OOM_PROTECTED; | |
| 246 } else { | |
| 247 #else | |
| 248 { | |
| 249 #endif | |
| 250 termination_status_ = | |
| 251 base::GetTerminationStatus(process_.Handle(), &exit_code_); | |
| 252 } | |
| 253 } | |
| 254 | |
| 221 void ChildProcessLauncher::Context::SetProcessBackgrounded(bool background) { | 255 void ChildProcessLauncher::Context::SetProcessBackgrounded(bool background) { |
| 222 base::Process to_pass = process_.Duplicate(); | 256 base::Process to_pass = process_.Duplicate(); |
| 223 BrowserThread::PostTask( | 257 BrowserThread::PostTask( |
| 224 BrowserThread::PROCESS_LAUNCHER, FROM_HERE, | 258 BrowserThread::PROCESS_LAUNCHER, FROM_HERE, |
| 225 base::Bind(&Context::SetProcessBackgroundedInternal, | 259 base::Bind(&Context::SetProcessBackgroundedInternal, |
| 226 base::Passed(&to_pass), background)); | 260 base::Passed(&to_pass), background)); |
| 227 } | 261 } |
| 228 | 262 |
| 229 // static | 263 // static |
| 230 void ChildProcessLauncher::Context::RecordHistograms( | 264 void ChildProcessLauncher::Context::RecordHistograms( |
| (...skipping 283 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 514 cmd_line, | 548 cmd_line, |
| 515 child_process_id, | 549 child_process_id, |
| 516 client); | 550 client); |
| 517 } | 551 } |
| 518 | 552 |
| 519 ChildProcessLauncher::~ChildProcessLauncher() { | 553 ChildProcessLauncher::~ChildProcessLauncher() { |
| 520 context_->ResetClient(); | 554 context_->ResetClient(); |
| 521 } | 555 } |
| 522 | 556 |
| 523 bool ChildProcessLauncher::IsStarting() { | 557 bool ChildProcessLauncher::IsStarting() { |
| 524 return context_->starting_; | 558 return context_->IsStarting(); |
| 525 } | 559 } |
| 526 | 560 |
| 527 const base::Process& ChildProcessLauncher::GetProcess() const { | 561 const base::Process& ChildProcessLauncher::GetProcess() const { |
| 528 DCHECK(!context_->starting_); | 562 DCHECK(!context_->IsStarting()); |
| 529 return context_->process_; | 563 return context_->GetProcess(); |
| 530 } | 564 } |
| 531 | 565 |
| 532 base::TerminationStatus ChildProcessLauncher::GetChildTerminationStatus( | 566 base::TerminationStatus ChildProcessLauncher::GetChildTerminationStatus( |
| 533 bool known_dead, | 567 bool known_dead, |
| 534 int* exit_code) { | 568 int* exit_code) { |
| 535 if (!context_->process_.IsValid()) { | 569 if (!context_->GetProcess().IsValid()) { |
| 536 // Process is already gone, so return the cached termination status. | 570 // Process is already gone, so return the cached termination status. |
| 537 if (exit_code) | 571 if (exit_code) |
| 538 *exit_code = context_->exit_code_; | 572 *exit_code = context_->exit_code(); |
| 539 return context_->termination_status_; | 573 return context_->termination_status(); |
| 540 } | |
| 541 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID) | |
| 542 if (context_->zygote_) { | |
| 543 context_->termination_status_ = ZygoteHostImpl::GetInstance()-> | |
| 544 GetTerminationStatus(context_->process_.Handle(), known_dead, | |
| 545 &context_->exit_code_); | |
| 546 } else if (known_dead) { | |
| 547 context_->termination_status_ = | |
| 548 base::GetKnownDeadTerminationStatus(context_->process_.Handle(), | |
| 549 &context_->exit_code_); | |
| 550 } else { | |
| 551 #elif defined(OS_MACOSX) | |
| 552 if (known_dead) { | |
| 553 context_->termination_status_ = | |
| 554 base::GetKnownDeadTerminationStatus(context_->process_.Handle(), | |
| 555 &context_->exit_code_); | |
| 556 } else { | |
| 557 #elif defined(OS_ANDROID) | |
| 558 if (IsChildProcessOomProtected(context_->process_.Handle())) { | |
| 559 context_->termination_status_ = base::TERMINATION_STATUS_OOM_PROTECTED; | |
| 560 } else { | |
| 561 #else | |
| 562 { | |
| 563 #endif | |
| 564 context_->GetTerminationStatus(); | |
| 565 } | 574 } |
| 566 | 575 |
| 576 context_->UpdateTerminationStatus(known_dead); | |
| 567 if (exit_code) | 577 if (exit_code) |
| 568 *exit_code = context_->exit_code_; | 578 *exit_code = context_->exit_code(); |
| 569 | 579 |
| 570 // POSIX: If the process crashed, then the kernel closed the socket | 580 // POSIX: If the process crashed, then the kernel closed the socket |
| 571 // for it and so the child has already died by the time we get | 581 // for it and so the child has already died by the time we get |
| 572 // here. Since GetTerminationStatus called waitpid with WNOHANG, | 582 // here. Since GetTerminationStatus called waitpid with WNOHANG, |
| 573 // it'll reap the process. However, if GetTerminationStatus didn't | 583 // it'll reap the process. However, if GetTerminationStatus didn't |
| 574 // reap the child (because it was still running), we'll need to | 584 // reap the child (because it was still running), we'll need to |
| 575 // Terminate via ProcessWatcher. So we can't close the handle here. | 585 // Terminate via ProcessWatcher. So we can't close the handle here. |
| 576 if (context_->termination_status_ != base::TERMINATION_STATUS_STILL_RUNNING) | 586 if (context_->termination_status() != base::TERMINATION_STATUS_STILL_RUNNING) |
| 577 context_->process_.Close(); | 587 context_->Close(); |
| 578 | 588 |
| 579 return context_->termination_status_; | 589 return context_->termination_status(); |
| 580 } | 590 } |
| 581 | 591 |
| 582 void ChildProcessLauncher::SetProcessBackgrounded(bool background) { | 592 void ChildProcessLauncher::SetProcessBackgrounded(bool background) { |
| 583 context_->SetProcessBackgrounded(background); | 593 context_->SetProcessBackgrounded(background); |
| 584 } | 594 } |
| 585 | 595 |
| 586 void ChildProcessLauncher::SetTerminateChildOnShutdown( | 596 void ChildProcessLauncher::SetTerminateChildOnShutdown( |
| 587 bool terminate_on_shutdown) { | 597 bool terminate_on_shutdown) { |
| 588 if (context_.get()) | 598 if (context_.get()) |
| 589 context_->set_terminate_child_on_shutdown(terminate_on_shutdown); | 599 context_->set_terminate_child_on_shutdown(terminate_on_shutdown); |
| 590 } | 600 } |
| 591 | 601 |
| 592 } // namespace content | 602 } // namespace content |
| OLD | NEW |