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.
5 #include "content/child/child_process.h"
7 #if defined(OS_POSIX) && !defined(OS_ANDROID)
8 #include <signal.h> // For SigUSR1Handler below.
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_impl.h"
21 #if defined(OS_ANDROID)
22 #include "base/debug/debugger.h"
25 #if defined(OS_POSIX) && !defined(OS_ANDROID)
26 static void SigUSR1Handler(int signal
) { }
33 base::LazyInstance
<base::ThreadLocalPointer
<ChildProcess
> > g_lazy_tls
=
34 LAZY_INSTANCE_INITIALIZER
;
37 ChildProcess::ChildProcess()
39 shutdown_event_(true, false),
40 io_thread_("Chrome_ChildIOThread") {
41 DCHECK(!g_lazy_tls
.Pointer()->Get());
42 g_lazy_tls
.Pointer()->Set(this);
44 base::StatisticsRecorder::Initialize();
46 // We can't recover from failing to start the IO thread.
47 base::Thread::Options
thread_options(base::MessageLoop::TYPE_IO
, 0);
48 #if defined(OS_ANDROID)
49 thread_options
.priority
= base::ThreadPriority::DISPLAY
;
51 CHECK(io_thread_
.StartWithOptions(thread_options
));
54 ChildProcess::~ChildProcess() {
55 DCHECK(g_lazy_tls
.Pointer()->Get() == this);
57 // Signal this event before destroying the child process. That way all
58 // background threads can cleanup.
59 // For example, in the renderer the RenderThread instances will be able to
60 // notice shutdown before the render process begins waiting for them to exit.
61 shutdown_event_
.Signal();
63 // Kill the main thread object before nulling child_process, since
64 // destruction code might depend on it.
65 if (main_thread_
) { // null in unittests.
66 main_thread_
->Shutdown();
70 g_lazy_tls
.Pointer()->Set(NULL
);
74 ChildThreadImpl
* ChildProcess::main_thread() {
75 return main_thread_
.get();
78 void ChildProcess::set_main_thread(ChildThreadImpl
* thread
) {
79 main_thread_
.reset(thread
);
82 void ChildProcess::AddRefProcess() {
83 DCHECK(!main_thread_
.get() || // null in unittests.
84 base::MessageLoop::current() == main_thread_
->message_loop());
88 void ChildProcess::ReleaseProcess() {
89 DCHECK(!main_thread_
.get() || // null in unittests.
90 base::MessageLoop::current() == main_thread_
->message_loop());
95 if (main_thread_
) // null in unittests.
96 main_thread_
->OnProcessFinalRelease();
99 ChildProcess
* ChildProcess::current() {
100 return g_lazy_tls
.Pointer()->Get();
103 base::WaitableEvent
* ChildProcess::GetShutDownEvent() {
104 return &shutdown_event_
;
107 void ChildProcess::WaitForDebugger(const std::string
& label
) {
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
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
, base::UTF8ToWide(message
).c_str(),
120 base::UTF8ToWide(title
).c_str(),
121 MB_OK
| MB_SETFOREGROUND
);
122 #elif defined(OS_POSIX)
123 #if defined(OS_ANDROID)
124 LOG(ERROR
) << label
<< " waiting for GDB.";
125 // Wait 24 hours for a debugger to be attached to the current process.
126 base::debug::WaitForDebugger(24 * 60 * 60, false);
128 // TODO(playmobil): In the long term, overriding this flag doesn't seem
129 // right, either use our own flag or open a dialog we can use.
130 // This is just to ease debugging in the interim.
134 << ") paused waiting for debugger to attach. "
135 << "Send SIGUSR1 to unpause.";
136 // Install a signal handler so that pause can be woken.
138 memset(&sa
, 0, sizeof(sa
));
139 sa
.sa_handler
= SigUSR1Handler
;
140 sigaction(SIGUSR1
, &sa
, NULL
);
143 #endif // defined(OS_ANDROID)
144 #endif // defined(OS_POSIX)
147 } // namespace content