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 }
73
main_thread()74 ChildThread* ChildProcess::main_thread() {
75 return main_thread_.get();
76 }
77
set_main_thread(ChildThread * thread)78 void ChildProcess::set_main_thread(ChildThread* thread) {
79 main_thread_.reset(thread);
80 }
81
AddRefProcess()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
ReleaseProcess()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
current()99 ChildProcess* ChildProcess::current() {
100 return g_lazy_tls.Pointer()->Get();
101 }
102
GetShutDownEvent()103 base::WaitableEvent* ChildProcess::GetShutDownEvent() {
104 return &shutdown_event_;
105 }
106
WaitForDebugger(const std::string & label)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