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 }
     73 
     74 ChildThread* ChildProcess::main_thread() {
     75   return main_thread_.get();
     76 }
     77 
     78 void ChildProcess::set_main_thread(ChildThread* thread) {
     79   main_thread_.reset(thread);
     80 }
     81 
     82 void ChildProcess::AddRefProcess() {
     83   DCHECK(!main_thread_.get() ||  // null in unittests.
     84          base::MessageLoop::current() == main_thread_->message_loop());
     85   ref_count_++;
     86 }
     87 
     88 void ChildProcess::ReleaseProcess() {
     89   DCHECK(!main_thread_.get() ||  // null in unittests.
     90          base::MessageLoop::current() == main_thread_->message_loop());
     91   DCHECK(ref_count_);
     92   if (--ref_count_)
     93     return;
     94 
     95   if (main_thread_)  // null in unittests.
     96     main_thread_->OnProcessFinalRelease();
     97 }
     98 
     99 ChildProcess* ChildProcess::current() {
    100   return g_lazy_tls.Pointer()->Get();
    101 }
    102 
    103 base::WaitableEvent* ChildProcess::GetShutDownEvent() {
    104   return &shutdown_event_;
    105 }
    106 
    107 void ChildProcess::WaitForDebugger(const std::string& label) {
    108 #if defined(OS_WIN)
    109 #if defined(GOOGLE_CHROME_BUILD)
    110   std::string title = "Google Chrome";
    111 #else  // CHROMIUM_BUILD
    112   std::string title = "Chromium";
    113 #endif  // CHROMIUM_BUILD
    114   title += " ";
    115   title += label;  // makes attaching to process easier
    116   std::string message = label;
    117   message += " starting with pid: ";
    118   message += base::IntToString(base::GetCurrentProcId());
    119   ::MessageBox(NULL, UTF8ToWide(message).c_str(), UTF8ToWide(title).c_str(),
    120                MB_OK | MB_SETFOREGROUND);
    121 #elif defined(OS_POSIX)
    122 #if defined(OS_ANDROID)
    123   LOG(ERROR) << label << " waiting for GDB.";
    124   // Wait 24 hours for a debugger to be attached to the current process.
    125   base::debug::WaitForDebugger(24 * 60 * 60, false);
    126 #else
    127   // TODO(playmobil): In the long term, overriding this flag doesn't seem
    128   // right, either use our own flag or open a dialog we can use.
    129   // This is just to ease debugging in the interim.
    130   LOG(ERROR) << label
    131              << " ("
    132              << getpid()
    133              << ") paused waiting for debugger to attach. "
    134              << "Send SIGUSR1 to unpause.";
    135   // Install a signal handler so that pause can be woken.
    136   struct sigaction sa;
    137   memset(&sa, 0, sizeof(sa));
    138   sa.sa_handler = SigUSR1Handler;
    139   sigaction(SIGUSR1, &sa, NULL);
    140 
    141   pause();
    142 #endif  // defined(OS_ANDROID)
    143 #endif  // defined(OS_POSIX)
    144 }
    145 
    146 }  // namespace content
    147