• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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)
SigUSR1Handler(int signal)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 
ChildProcess()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 
~ChildProcess()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 
main_thread()75 ChildThread* ChildProcess::main_thread() {
76   return main_thread_.get();
77 }
78 
set_main_thread(ChildThread * thread)79 void ChildProcess::set_main_thread(ChildThread* thread) {
80   main_thread_.reset(thread);
81 }
82 
AddRefProcess()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 
ReleaseProcess()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 
current()100 ChildProcess* ChildProcess::current() {
101   return g_lazy_tls.Pointer()->Get();
102 }
103 
GetShutDownEvent()104 base::WaitableEvent* ChildProcess::GetShutDownEvent() {
105   return &shutdown_event_;
106 }
107 
WaitForDebugger(const std::string & label)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