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); 720529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch io_thread_.Stop(); 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ChildThread* ChildProcess::main_thread() { 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return main_thread_.get(); 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ChildProcess::set_main_thread(ChildThread* thread) { 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) main_thread_.reset(thread); 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ChildProcess::AddRefProcess() { 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!main_thread_.get() || // null in unittests. 85c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::MessageLoop::current() == main_thread_->message_loop()); 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ref_count_++; 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ChildProcess::ReleaseProcess() { 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!main_thread_.get() || // null in unittests. 91c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::MessageLoop::current() == main_thread_->message_loop()); 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(ref_count_); 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (--ref_count_) 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 96c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (main_thread_) // null in unittests. 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) main_thread_->OnProcessFinalRelease(); 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)ChildProcess* ChildProcess::current() { 101eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return g_lazy_tls.Pointer()->Get(); 10290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 10390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)base::WaitableEvent* ChildProcess::GetShutDownEvent() { 105eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return &shutdown_event_; 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ChildProcess::WaitForDebugger(const std::string& label) { 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN) 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(GOOGLE_CHROME_BUILD) 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string title = "Google Chrome"; 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else // CHROMIUM_BUILD 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string title = "Chromium"; 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // CHROMIUM_BUILD 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) title += " "; 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) title += label; // makes attaching to process easier 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string message = label; 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) message += " starting with pid: "; 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) message += base::IntToString(base::GetCurrentProcId()); 1205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ::MessageBox(NULL, base::UTF8ToWide(message).c_str(), 1215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::UTF8ToWide(title).c_str(), 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MB_OK | MB_SETFOREGROUND); 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_POSIX) 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_ANDROID) 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << label << " waiting for GDB."; 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Wait 24 hours for a debugger to be attached to the current process. 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::debug::WaitForDebugger(24 * 60 * 60, false); 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(playmobil): In the long term, overriding this flag doesn't seem 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // right, either use our own flag or open a dialog we can use. 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This is just to ease debugging in the interim. 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << label 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << " (" 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << getpid() 1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) << ") paused waiting for debugger to attach. " 1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) << "Send SIGUSR1 to unpause."; 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Install a signal handler so that pause can be woken. 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct sigaction sa; 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memset(&sa, 0, sizeof(sa)); 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sa.sa_handler = SigUSR1Handler; 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sigaction(SIGUSR1, &sa, NULL); 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pause(); 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // defined(OS_ANDROID) 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // defined(OS_POSIX) 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace content 149