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