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_thread.h" 6 7 #include <string> 8 9 #include "base/allocator/allocator_extension.h" 10 #include "base/base_switches.h" 11 #include "base/command_line.h" 12 #include "base/debug/leak_annotations.h" 13 #include "base/lazy_instance.h" 14 #include "base/message_loop/message_loop.h" 15 #include "base/process/kill.h" 16 #include "base/process/process_handle.h" 17 #include "base/strings/string_util.h" 18 #include "base/synchronization/condition_variable.h" 19 #include "base/synchronization/lock.h" 20 #include "base/threading/thread_local.h" 21 #include "base/tracked_objects.h" 22 #include "components/tracing/child_trace_message_filter.h" 23 #include "content/child/child_histogram_message_filter.h" 24 #include "content/child/child_process.h" 25 #include "content/child/child_resource_message_filter.h" 26 #include "content/child/fileapi/file_system_dispatcher.h" 27 #include "content/child/power_monitor_broadcast_source.h" 28 #include "content/child/quota_dispatcher.h" 29 #include "content/child/quota_message_filter.h" 30 #include "content/child/resource_dispatcher.h" 31 #include "content/child/service_worker/service_worker_dispatcher.h" 32 #include "content/child/service_worker/service_worker_message_filter.h" 33 #include "content/child/socket_stream_dispatcher.h" 34 #include "content/child/thread_safe_sender.h" 35 #include "content/child/websocket_dispatcher.h" 36 #include "content/common/child_process_messages.h" 37 #include "content/public/common/content_switches.h" 38 #include "ipc/ipc_logging.h" 39 #include "ipc/ipc_switches.h" 40 #include "ipc/ipc_sync_channel.h" 41 #include "ipc/ipc_sync_message_filter.h" 42 43 #if defined(OS_WIN) 44 #include "content/common/handle_enumerator_win.h" 45 #endif 46 47 #if defined(TCMALLOC_TRACE_MEMORY_SUPPORTED) 48 #include "third_party/tcmalloc/chromium/src/gperftools/heap-profiler.h" 49 #endif 50 51 using tracked_objects::ThreadData; 52 53 namespace content { 54 namespace { 55 56 // How long to wait for a connection to the browser process before giving up. 57 const int kConnectionTimeoutS = 15; 58 59 base::LazyInstance<base::ThreadLocalPointer<ChildThread> > g_lazy_tls = 60 LAZY_INSTANCE_INITIALIZER; 61 62 // This isn't needed on Windows because there the sandbox's job object 63 // terminates child processes automatically. For unsandboxed processes (i.e. 64 // plugins), PluginThread has EnsureTerminateMessageFilter. 65 #if defined(OS_POSIX) 66 67 class SuicideOnChannelErrorFilter : public IPC::ChannelProxy::MessageFilter { 68 public: 69 // IPC::ChannelProxy::MessageFilter 70 virtual void OnChannelError() OVERRIDE { 71 // For renderer/worker processes: 72 // On POSIX, at least, one can install an unload handler which loops 73 // forever and leave behind a renderer process which eats 100% CPU forever. 74 // 75 // This is because the terminate signals (ViewMsg_ShouldClose and the error 76 // from the IPC channel) are routed to the main message loop but never 77 // processed (because that message loop is stuck in V8). 78 // 79 // One could make the browser SIGKILL the renderers, but that leaves open a 80 // large window where a browser failure (or a user, manually terminating 81 // the browser because "it's stuck") will leave behind a process eating all 82 // the CPU. 83 // 84 // So, we install a filter on the channel so that we can process this event 85 // here and kill the process. 86 if (CommandLine::ForCurrentProcess()-> 87 HasSwitch(switches::kChildCleanExit)) { 88 // If clean exit is requested, we want to kill this process after giving 89 // it 60 seconds to run exit handlers. Exit handlers may including ones 90 // that write profile data to disk (which happens under profile collection 91 // mode). 92 alarm(60); 93 #if defined(LEAK_SANITIZER) 94 // Invoke LeakSanitizer early to avoid detecting shutdown-only leaks. If 95 // leaks are found, the process will exit here. 96 __lsan_do_leak_check(); 97 #endif 98 } else { 99 _exit(0); 100 } 101 } 102 103 protected: 104 virtual ~SuicideOnChannelErrorFilter() {} 105 }; 106 107 #endif // OS(POSIX) 108 109 #if defined(OS_ANDROID) 110 ChildThread* g_child_thread = NULL; 111 112 // A lock protects g_child_thread. 113 base::LazyInstance<base::Lock> g_lazy_child_thread_lock = 114 LAZY_INSTANCE_INITIALIZER; 115 116 // base::ConditionVariable has an explicit constructor that takes 117 // a base::Lock pointer as parameter. The base::DefaultLazyInstanceTraits 118 // doesn't handle the case. Thus, we need our own class here. 119 struct CondVarLazyInstanceTraits { 120 static const bool kRegisterOnExit = true; 121 static const bool kAllowedToAccessOnNonjoinableThread ALLOW_UNUSED = false; 122 static base::ConditionVariable* New(void* instance) { 123 return new (instance) base::ConditionVariable( 124 g_lazy_child_thread_lock.Pointer()); 125 } 126 static void Delete(base::ConditionVariable* instance) { 127 instance->~ConditionVariable(); 128 } 129 }; 130 131 // A condition variable that synchronize threads initializing and waiting 132 // for g_child_thread. 133 base::LazyInstance<base::ConditionVariable, CondVarLazyInstanceTraits> 134 g_lazy_child_thread_cv = LAZY_INSTANCE_INITIALIZER; 135 136 void QuitMainThreadMessageLoop() { 137 base::MessageLoop::current()->Quit(); 138 } 139 140 #endif 141 142 } // namespace 143 144 ChildThread::ChildThread() 145 : channel_connected_factory_(this), 146 in_browser_process_(false) { 147 channel_name_ = CommandLine::ForCurrentProcess()->GetSwitchValueASCII( 148 switches::kProcessChannelID); 149 Init(); 150 } 151 152 ChildThread::ChildThread(const std::string& channel_name) 153 : channel_name_(channel_name), 154 channel_connected_factory_(this), 155 in_browser_process_(true) { 156 Init(); 157 } 158 159 void ChildThread::Init() { 160 g_lazy_tls.Pointer()->Set(this); 161 on_channel_error_called_ = false; 162 message_loop_ = base::MessageLoop::current(); 163 #ifdef IPC_MESSAGE_LOG_ENABLED 164 // We must make sure to instantiate the IPC Logger *before* we create the 165 // channel, otherwise we can get a callback on the IO thread which creates 166 // the logger, and the logger does not like being created on the IO thread. 167 IPC::Logging::GetInstance(); 168 #endif 169 channel_.reset( 170 new IPC::SyncChannel(channel_name_, 171 IPC::Channel::MODE_CLIENT, 172 this, 173 ChildProcess::current()->io_message_loop_proxy(), 174 true, 175 ChildProcess::current()->GetShutDownEvent())); 176 #ifdef IPC_MESSAGE_LOG_ENABLED 177 if (!in_browser_process_) 178 IPC::Logging::GetInstance()->SetIPCSender(this); 179 #endif 180 181 sync_message_filter_ = 182 new IPC::SyncMessageFilter(ChildProcess::current()->GetShutDownEvent()); 183 thread_safe_sender_ = new ThreadSafeSender( 184 base::MessageLoopProxy::current().get(), sync_message_filter_.get()); 185 186 resource_dispatcher_.reset(new ResourceDispatcher(this)); 187 socket_stream_dispatcher_.reset(new SocketStreamDispatcher()); 188 websocket_dispatcher_.reset(new WebSocketDispatcher); 189 file_system_dispatcher_.reset(new FileSystemDispatcher()); 190 191 histogram_message_filter_ = new ChildHistogramMessageFilter(); 192 resource_message_filter_ = 193 new ChildResourceMessageFilter(resource_dispatcher()); 194 195 service_worker_message_filter_ = 196 new ServiceWorkerMessageFilter(thread_safe_sender_.get()); 197 service_worker_dispatcher_.reset( 198 new ServiceWorkerDispatcher(thread_safe_sender_.get())); 199 200 quota_message_filter_ = 201 new QuotaMessageFilter(thread_safe_sender_.get()); 202 quota_dispatcher_.reset(new QuotaDispatcher(thread_safe_sender_.get(), 203 quota_message_filter_.get())); 204 205 channel_->AddFilter(histogram_message_filter_.get()); 206 channel_->AddFilter(sync_message_filter_.get()); 207 channel_->AddFilter(new tracing::ChildTraceMessageFilter( 208 ChildProcess::current()->io_message_loop_proxy())); 209 channel_->AddFilter(resource_message_filter_.get()); 210 channel_->AddFilter(quota_message_filter_->GetFilter()); 211 channel_->AddFilter(service_worker_message_filter_->GetFilter()); 212 213 // In single process mode we may already have a power monitor 214 if (!base::PowerMonitor::Get()) { 215 scoped_ptr<PowerMonitorBroadcastSource> power_monitor_source( 216 new PowerMonitorBroadcastSource()); 217 channel_->AddFilter(power_monitor_source->GetMessageFilter()); 218 219 power_monitor_.reset(new base::PowerMonitor( 220 power_monitor_source.PassAs<base::PowerMonitorSource>())); 221 } 222 223 #if defined(OS_POSIX) 224 // Check that --process-type is specified so we don't do this in unit tests 225 // and single-process mode. 226 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kProcessType)) 227 channel_->AddFilter(new SuicideOnChannelErrorFilter()); 228 #endif 229 230 base::MessageLoop::current()->PostDelayedTask( 231 FROM_HERE, 232 base::Bind(&ChildThread::EnsureConnected, 233 channel_connected_factory_.GetWeakPtr()), 234 base::TimeDelta::FromSeconds(kConnectionTimeoutS)); 235 236 #if defined(OS_ANDROID) 237 { 238 base::AutoLock lock(g_lazy_child_thread_lock.Get()); 239 g_child_thread = this; 240 } 241 // Signalling without locking is fine here because only 242 // one thread can wait on the condition variable. 243 g_lazy_child_thread_cv.Get().Signal(); 244 #endif 245 246 #if defined(TCMALLOC_TRACE_MEMORY_SUPPORTED) 247 trace_memory_controller_.reset(new base::debug::TraceMemoryController( 248 message_loop_->message_loop_proxy(), 249 ::HeapProfilerWithPseudoStackStart, 250 ::HeapProfilerStop, 251 ::GetHeapProfile)); 252 #endif 253 } 254 255 ChildThread::~ChildThread() { 256 #ifdef IPC_MESSAGE_LOG_ENABLED 257 IPC::Logging::GetInstance()->SetIPCSender(NULL); 258 #endif 259 260 channel_->RemoveFilter(histogram_message_filter_.get()); 261 channel_->RemoveFilter(sync_message_filter_.get()); 262 263 // The ChannelProxy object caches a pointer to the IPC thread, so need to 264 // reset it as it's not guaranteed to outlive this object. 265 // NOTE: this also has the side-effect of not closing the main IPC channel to 266 // the browser process. This is needed because this is the signal that the 267 // browser uses to know that this process has died, so we need it to be alive 268 // until this process is shut down, and the OS closes the handle 269 // automatically. We used to watch the object handle on Windows to do this, 270 // but it wasn't possible to do so on POSIX. 271 channel_->ClearIPCTaskRunner(); 272 g_lazy_tls.Pointer()->Set(NULL); 273 } 274 275 void ChildThread::Shutdown() { 276 // Delete objects that hold references to blink so derived classes can 277 // safely shutdown blink in their Shutdown implementation. 278 file_system_dispatcher_.reset(); 279 quota_dispatcher_.reset(); 280 } 281 282 void ChildThread::OnChannelConnected(int32 peer_pid) { 283 channel_connected_factory_.InvalidateWeakPtrs(); 284 } 285 286 void ChildThread::OnChannelError() { 287 set_on_channel_error_called(true); 288 base::MessageLoop::current()->Quit(); 289 } 290 291 bool ChildThread::Send(IPC::Message* msg) { 292 DCHECK(base::MessageLoop::current() == message_loop()); 293 if (!channel_) { 294 delete msg; 295 return false; 296 } 297 298 return channel_->Send(msg); 299 } 300 301 void ChildThread::AddRoute(int32 routing_id, IPC::Listener* listener) { 302 DCHECK(base::MessageLoop::current() == message_loop()); 303 304 router_.AddRoute(routing_id, listener); 305 } 306 307 void ChildThread::RemoveRoute(int32 routing_id) { 308 DCHECK(base::MessageLoop::current() == message_loop()); 309 310 router_.RemoveRoute(routing_id); 311 } 312 313 webkit_glue::ResourceLoaderBridge* ChildThread::CreateBridge( 314 const webkit_glue::ResourceLoaderBridge::RequestInfo& request_info) { 315 return resource_dispatcher()->CreateBridge(request_info); 316 } 317 318 base::SharedMemory* ChildThread::AllocateSharedMemory(size_t buf_size) { 319 return AllocateSharedMemory(buf_size, this); 320 } 321 322 // static 323 base::SharedMemory* ChildThread::AllocateSharedMemory( 324 size_t buf_size, 325 IPC::Sender* sender) { 326 scoped_ptr<base::SharedMemory> shared_buf; 327 #if defined(OS_WIN) 328 shared_buf.reset(new base::SharedMemory); 329 if (!shared_buf->CreateAndMapAnonymous(buf_size)) { 330 NOTREACHED(); 331 return NULL; 332 } 333 #else 334 // On POSIX, we need to ask the browser to create the shared memory for us, 335 // since this is blocked by the sandbox. 336 base::SharedMemoryHandle shared_mem_handle; 337 if (sender->Send(new ChildProcessHostMsg_SyncAllocateSharedMemory( 338 buf_size, &shared_mem_handle))) { 339 if (base::SharedMemory::IsHandleValid(shared_mem_handle)) { 340 shared_buf.reset(new base::SharedMemory(shared_mem_handle, false)); 341 if (!shared_buf->Map(buf_size)) { 342 NOTREACHED() << "Map failed"; 343 return NULL; 344 } 345 } else { 346 NOTREACHED() << "Browser failed to allocate shared memory"; 347 return NULL; 348 } 349 } else { 350 NOTREACHED() << "Browser allocation request message failed"; 351 return NULL; 352 } 353 #endif 354 return shared_buf.release(); 355 } 356 357 bool ChildThread::OnMessageReceived(const IPC::Message& msg) { 358 // Resource responses are sent to the resource dispatcher. 359 if (resource_dispatcher_->OnMessageReceived(msg)) 360 return true; 361 if (socket_stream_dispatcher_->OnMessageReceived(msg)) 362 return true; 363 if (websocket_dispatcher_->OnMessageReceived(msg)) 364 return true; 365 if (file_system_dispatcher_->OnMessageReceived(msg)) 366 return true; 367 368 bool handled = true; 369 IPC_BEGIN_MESSAGE_MAP(ChildThread, msg) 370 IPC_MESSAGE_HANDLER(ChildProcessMsg_Shutdown, OnShutdown) 371 #if defined(IPC_MESSAGE_LOG_ENABLED) 372 IPC_MESSAGE_HANDLER(ChildProcessMsg_SetIPCLoggingEnabled, 373 OnSetIPCLoggingEnabled) 374 #endif 375 IPC_MESSAGE_HANDLER(ChildProcessMsg_SetProfilerStatus, 376 OnSetProfilerStatus) 377 IPC_MESSAGE_HANDLER(ChildProcessMsg_GetChildProfilerData, 378 OnGetChildProfilerData) 379 IPC_MESSAGE_HANDLER(ChildProcessMsg_DumpHandles, OnDumpHandles) 380 #if defined(USE_TCMALLOC) 381 IPC_MESSAGE_HANDLER(ChildProcessMsg_GetTcmallocStats, OnGetTcmallocStats) 382 #endif 383 IPC_MESSAGE_UNHANDLED(handled = false) 384 IPC_END_MESSAGE_MAP() 385 386 if (handled) 387 return true; 388 389 if (msg.routing_id() == MSG_ROUTING_CONTROL) 390 return OnControlMessageReceived(msg); 391 392 return router_.OnMessageReceived(msg); 393 } 394 395 bool ChildThread::OnControlMessageReceived(const IPC::Message& msg) { 396 return false; 397 } 398 399 void ChildThread::OnShutdown() { 400 base::MessageLoop::current()->Quit(); 401 } 402 403 #if defined(IPC_MESSAGE_LOG_ENABLED) 404 void ChildThread::OnSetIPCLoggingEnabled(bool enable) { 405 if (enable) 406 IPC::Logging::GetInstance()->Enable(); 407 else 408 IPC::Logging::GetInstance()->Disable(); 409 } 410 #endif // IPC_MESSAGE_LOG_ENABLED 411 412 void ChildThread::OnSetProfilerStatus(ThreadData::Status status) { 413 ThreadData::InitializeAndSetTrackingStatus(status); 414 } 415 416 void ChildThread::OnGetChildProfilerData(int sequence_number) { 417 tracked_objects::ProcessDataSnapshot process_data; 418 ThreadData::Snapshot(false, &process_data); 419 420 Send(new ChildProcessHostMsg_ChildProfilerData(sequence_number, 421 process_data)); 422 } 423 424 void ChildThread::OnDumpHandles() { 425 #if defined(OS_WIN) 426 scoped_refptr<HandleEnumerator> handle_enum( 427 new HandleEnumerator( 428 CommandLine::ForCurrentProcess()->HasSwitch( 429 switches::kAuditAllHandles))); 430 handle_enum->EnumerateHandles(); 431 Send(new ChildProcessHostMsg_DumpHandlesDone); 432 return; 433 #endif 434 435 NOTIMPLEMENTED(); 436 } 437 438 #if defined(USE_TCMALLOC) 439 void ChildThread::OnGetTcmallocStats() { 440 std::string result; 441 char buffer[1024 * 32]; 442 base::allocator::GetStats(buffer, sizeof(buffer)); 443 result.append(buffer); 444 Send(new ChildProcessHostMsg_TcmallocStats(result)); 445 } 446 #endif 447 448 ChildThread* ChildThread::current() { 449 return g_lazy_tls.Pointer()->Get(); 450 } 451 452 #if defined(OS_ANDROID) 453 // The method must NOT be called on the child thread itself. 454 // It may block the child thread if so. 455 void ChildThread::ShutdownThread() { 456 DCHECK(!ChildThread::current()) << 457 "this method should NOT be called from child thread itself"; 458 { 459 base::AutoLock lock(g_lazy_child_thread_lock.Get()); 460 while (!g_child_thread) 461 g_lazy_child_thread_cv.Get().Wait(); 462 } 463 DCHECK_NE(base::MessageLoop::current(), g_child_thread->message_loop()); 464 g_child_thread->message_loop()->PostTask( 465 FROM_HERE, base::Bind(&QuitMainThreadMessageLoop)); 466 } 467 468 #endif 469 470 void ChildThread::OnProcessFinalRelease() { 471 if (on_channel_error_called_) { 472 base::MessageLoop::current()->Quit(); 473 return; 474 } 475 476 // The child process shutdown sequence is a request response based mechanism, 477 // where we send out an initial feeler request to the child process host 478 // instance in the browser to verify if it's ok to shutdown the child process. 479 // The browser then sends back a response if it's ok to shutdown. This avoids 480 // race conditions if the process refcount is 0 but there's an IPC message 481 // inflight that would addref it. 482 Send(new ChildProcessHostMsg_ShutdownRequest); 483 } 484 485 void ChildThread::EnsureConnected() { 486 VLOG(0) << "ChildThread::EnsureConnected()"; 487 base::KillProcess(base::GetCurrentProcessHandle(), 0, false); 488 } 489 490 } // namespace content 491