Home | History | Annotate | Download | only in child
      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
      3 // found in the LICENSE file.
      4 
      5 #include "content/child/child_process.h"
      6 
      7 #if defined(OS_POSIX) && !defined(OS_ANDROID)
      8 #include <signal.h>  // For SigUSR1Handler below.
      9 #endif
     10 
     11 #include "base/lazy_instance.h"
     12 #include "base/message_loop/message_loop.h"
     13 #include "base/metrics/statistics_recorder.h"
     14 #include "base/process/process_handle.h"
     15 #include "base/strings/string_number_conversions.h"
     16 #include "base/strings/utf_string_conversions.h"
     17 #include "base/threading/thread.h"
     18 #include "base/threading/thread_local.h"
     19 #include "content/child/child_thread.h"
     20 
     21 #if defined(OS_ANDROID)
     22 #include "base/debug/debugger.h"
     23 #endif
     24 
     25 #if defined(OS_POSIX) && !defined(OS_ANDROID)
     26 static void SigUSR1Handler(int signal) { }
     27 #endif
     28 
     29 namespace content {
     30 
     31 namespace {
     32 
     33 base::LazyInstance<base::ThreadLocalPointer<ChildProcess> > g_lazy_tls =
     34     LAZY_INSTANCE_INITIALIZER;
     35 }
     36 
     37 ChildProcess::ChildProcess()
     38     : ref_count_(0),
     39       shutdown_event_(true, false),
     40       io_thread_("Chrome_ChildIOThread") {
     41   DCHECK(!g_lazy_tls.Pointer()->Get());
     42   g_lazy_tls.Pointer()->Set(this);
     43 
     44   base::StatisticsRecorder::Initialize();
     45 
     46   // We can't recover from failing to start the IO thread.
     47   CHECK(io_thread_.StartWithOptions(
     48       base::Thread::Options(base::MessageLoop::TYPE_IO, 0)));
     49 
     50 #if defined(OS_ANDROID)
     51   io_thread_.SetPriority(base::kThreadPriority_Display);
     52 #endif
     53 }
     54 
     55 ChildProcess::~ChildProcess() {
     56   DCHECK(g_lazy_tls.Pointer()->Get() == this);
     57 
     58   // Signal this event before destroying the child process.  That way all
     59   // background threads can cleanup.
     60   // For example, in the renderer the RenderThread instances will be able to
     61   // notice shutdown before the render process begins waiting for them to exit.
     62   shutdown_event_.Signal();
     63 
     64   // Kill the main thread object before nulling child_process, since
     65   // destruction code might depend on it.
     66   if (main_thread_) {  // null in unittests.
     67     main_thread_->Shutdown();
     68     main_thread_.reset();
     69   }
     70 
     71   g_lazy_tls.Pointer()->Set(NULL);
     72   io_thread_.Stop();
     73 }
     74 
     75 ChildThread* ChildProcess::main_thread() {
     76   return main_thread_.get();
     77 }
     78 
     79 void ChildProcess::set_main_thread(ChildThread* thread) {
     80   main_thread_.reset(thread);
     81 }
     82 
     83 void ChildProcess::AddRefProcess() {
     84   DCHECK(!main_thread_.get() ||  // null in unittests.
     85          base::MessageLoop::current() == main_thread_->message_loop());
     86   ref_count_++;
     87 }
     88 
     89 void ChildProcess::ReleaseProcess() {
     90   DCHECK(!main_thread_.get() ||  // null in unittests.
     91          base::MessageLoop::current() == main_thread_->message_loop());
     92   DCHECK(ref_count_);
     93   if (--ref_count_)
     94     return;
     95 
     96   if (main_thread_)  // null in unittests.
     97     main_thread_->OnProcessFinalRelease();
     98 }
     99 
    100 ChildProcess* ChildProcess::current() {
    101   return g_lazy_tls.Pointer()->Get();
    102 }
    103 
    104 base::WaitableEvent* ChildProcess::GetShutDownEvent() {
    105   return &shutdown_event_;
    106 }
    107 
    108 void ChildProcess::WaitForDebugger(const std::string& label) {
    109 #if defined(OS_WIN)
    110 #if defined(GOOGLE_CHROME_BUILD)
    111   std::string title = "Google Chrome";
    112 #else  // CHROMIUM_BUILD
    113   std::string title = "Chromium";
    114 #endif  // CHROMIUM_BUILD
    115   title += " ";
    116   title += label;  // makes attaching to process easier
    117   std::string message = label;
    118   message += " starting with pid: ";
    119   message += base::IntToString(base::GetCurrentProcId());
    120   ::MessageBox(NULL, base::UTF8ToWide(message).c_str(),
    121                base::UTF8ToWide(title).c_str(),
    122                MB_OK | MB_SETFOREGROUND);
    123 #elif defined(OS_POSIX)
    124 #if defined(OS_ANDROID)
    125   LOG(ERROR) << label << " waiting for GDB.";
    126   // Wait 24 hours for a debugger to be attached to the current process.
    127   base::debug::WaitForDebugger(24 * 60 * 60, false);
    128 #else
    129   // TODO(playmobil): In the long term, overriding this flag doesn't seem
    130   // right, either use our own flag or open a dialog we can use.
    131   // This is just to ease debugging in the interim.
    132   LOG(ERROR) << label
    133              << " ("
    134              << getpid()
    135              << ") paused waiting for debugger to attach. "
    136              << "Send SIGUSR1 to unpause.";
    137   // Install a signal handler so that pause can be woken.
    138   struct sigaction sa;
    139   memset(&sa, 0, sizeof(sa));
    140   sa.sa_handler = SigUSR1Handler;
    141   sigaction(SIGUSR1, &sa, NULL);
    142 
    143   pause();
    144 #endif  // defined(OS_ANDROID)
    145 #endif  // defined(OS_POSIX)
    146 }
    147 
    148 }  // namespace content
    149