15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "content/child/child_process.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_POSIX) && !defined(OS_ANDROID) 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <signal.h> // For SigUSR1Handler below. 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/lazy_instance.h" 129ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "base/message_loop/message_loop.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/metrics/statistics_recorder.h" 1458e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch#include "base/process/process_handle.h" 15868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_number_conversions.h" 16868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/thread.h" 18eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/threading/thread_local.h" 19868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "content/child/child_thread.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_ANDROID) 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/debug/debugger.h" 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_POSIX) && !defined(OS_ANDROID) 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void SigUSR1Handler(int signal) { } 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace content { 30eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 31eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochnamespace { 32eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 33eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochbase::LazyInstance<base::ThreadLocalPointer<ChildProcess> > g_lazy_tls = 34eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch LAZY_INSTANCE_INITIALIZER; 35eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ChildProcess::ChildProcess() 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : ref_count_(0), 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shutdown_event_(true, false), 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) io_thread_("Chrome_ChildIOThread") { 41eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch DCHECK(!g_lazy_tls.Pointer()->Get()); 42eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch g_lazy_tls.Pointer()->Set(this); 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::StatisticsRecorder::Initialize(); 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We can't recover from failing to start the IO thread. 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(io_thread_.StartWithOptions( 48c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::Thread::Options(base::MessageLoop::TYPE_IO, 0))); 492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(OS_ANDROID) 5190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) io_thread_.SetPriority(base::kThreadPriority_Display); 522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ChildProcess::~ChildProcess() { 56eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch DCHECK(g_lazy_tls.Pointer()->Get() == this); 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Signal this event before destroying the child process. That way all 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // background threads can cleanup. 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // For example, in the renderer the RenderThread instances will be able to 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // notice shutdown before the render process begins waiting for them to exit. 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shutdown_event_.Signal(); 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Kill the main thread object before nulling child_process, since 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // destruction code might depend on it. 66c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (main_thread_) { // null in unittests. 67c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) main_thread_->Shutdown(); 68c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) main_thread_.reset(); 69c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 71eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch g_lazy_tls.Pointer()->Set(NULL); 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ChildThread* ChildProcess::main_thread() { 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return main_thread_.get(); 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ChildProcess::set_main_thread(ChildThread* thread) { 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) main_thread_.reset(thread); 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ChildProcess::AddRefProcess() { 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!main_thread_.get() || // null in unittests. 84c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::MessageLoop::current() == main_thread_->message_loop()); 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ref_count_++; 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ChildProcess::ReleaseProcess() { 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!main_thread_.get() || // null in unittests. 90c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::MessageLoop::current() == main_thread_->message_loop()); 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(ref_count_); 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (--ref_count_) 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (main_thread_) // null in unittests. 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) main_thread_->OnProcessFinalRelease(); 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)ChildProcess* ChildProcess::current() { 100eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return g_lazy_tls.Pointer()->Get(); 10190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 10290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)base::WaitableEvent* ChildProcess::GetShutDownEvent() { 104eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return &shutdown_event_; 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ChildProcess::WaitForDebugger(const std::string& label) { 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN) 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(GOOGLE_CHROME_BUILD) 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string title = "Google Chrome"; 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else // CHROMIUM_BUILD 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string title = "Chromium"; 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // CHROMIUM_BUILD 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) title += " "; 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) title += label; // makes attaching to process easier 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string message = label; 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) message += " starting with pid: "; 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) message += base::IntToString(base::GetCurrentProcId()); 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::MessageBox(NULL, UTF8ToWide(message).c_str(), UTF8ToWide(title).c_str(), 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MB_OK | MB_SETFOREGROUND); 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_POSIX) 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_ANDROID) 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << label << " waiting for GDB."; 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Wait 24 hours for a debugger to be attached to the current process. 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::debug::WaitForDebugger(24 * 60 * 60, false); 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(playmobil): In the long term, overriding this flag doesn't seem 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // right, either use our own flag or open a dialog we can use. 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This is just to ease debugging in the interim. 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << label 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << " (" 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << getpid() 1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) << ") paused waiting for debugger to attach. " 1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) << "Send SIGUSR1 to unpause."; 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Install a signal handler so that pause can be woken. 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct sigaction sa; 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memset(&sa, 0, sizeof(sa)); 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sa.sa_handler = SigUSR1Handler; 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sigaction(SIGUSR1, &sa, NULL); 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pause(); 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // defined(OS_ANDROID) 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // defined(OS_POSIX) 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace content 147