OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "content/child/child_thread_impl.h" | 5 #include "content/child/child_thread_impl.h" |
6 | 6 |
7 #include <signal.h> | 7 #include <signal.h> |
8 | 8 |
9 #include <string> | 9 #include <string> |
10 | 10 |
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
154 } | 154 } |
155 | 155 |
156 protected: | 156 protected: |
157 ~SuicideOnChannelErrorFilter() override {} | 157 ~SuicideOnChannelErrorFilter() override {} |
158 }; | 158 }; |
159 | 159 |
160 #endif // OS(POSIX) | 160 #endif // OS(POSIX) |
161 | 161 |
162 #if defined(OS_ANDROID) | 162 #if defined(OS_ANDROID) |
163 ChildThreadImpl* g_child_thread = NULL; | 163 ChildThreadImpl* g_child_thread = NULL; |
| 164 bool g_child_thread_initialized = false; |
164 | 165 |
165 // A lock protects g_child_thread. | 166 // A lock protects g_child_thread. |
166 base::LazyInstance<base::Lock> g_lazy_child_thread_lock = | 167 base::LazyInstance<base::Lock>::Leaky g_lazy_child_thread_lock = |
167 LAZY_INSTANCE_INITIALIZER; | 168 LAZY_INSTANCE_INITIALIZER; |
168 | 169 |
169 // base::ConditionVariable has an explicit constructor that takes | 170 // base::ConditionVariable has an explicit constructor that takes |
170 // a base::Lock pointer as parameter. The base::DefaultLazyInstanceTraits | 171 // a base::Lock pointer as parameter. The base::DefaultLazyInstanceTraits |
171 // doesn't handle the case. Thus, we need our own class here. | 172 // doesn't handle the case. Thus, we need our own class here. |
172 struct CondVarLazyInstanceTraits { | 173 struct CondVarLazyInstanceTraits { |
173 static const bool kRegisterOnExit = true; | 174 static const bool kRegisterOnExit = false; |
174 #ifndef NDEBUG | 175 #ifndef NDEBUG |
175 static const bool kAllowedToAccessOnNonjoinableThread = false; | 176 static const bool kAllowedToAccessOnNonjoinableThread = true; |
176 #endif | 177 #endif |
177 | 178 |
178 static base::ConditionVariable* New(void* instance) { | 179 static base::ConditionVariable* New(void* instance) { |
179 return new (instance) base::ConditionVariable( | 180 return new (instance) base::ConditionVariable( |
180 g_lazy_child_thread_lock.Pointer()); | 181 g_lazy_child_thread_lock.Pointer()); |
181 } | 182 } |
182 static void Delete(base::ConditionVariable* instance) { | 183 static void Delete(base::ConditionVariable* instance) { |
183 instance->~ConditionVariable(); | 184 instance->~ConditionVariable(); |
184 } | 185 } |
185 }; | 186 }; |
(...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
366 base::MessageLoop::current()->PostDelayedTask( | 367 base::MessageLoop::current()->PostDelayedTask( |
367 FROM_HERE, | 368 FROM_HERE, |
368 base::Bind(&ChildThreadImpl::EnsureConnected, | 369 base::Bind(&ChildThreadImpl::EnsureConnected, |
369 channel_connected_factory_.GetWeakPtr()), | 370 channel_connected_factory_.GetWeakPtr()), |
370 base::TimeDelta::FromSeconds(connection_timeout)); | 371 base::TimeDelta::FromSeconds(connection_timeout)); |
371 | 372 |
372 #if defined(OS_ANDROID) | 373 #if defined(OS_ANDROID) |
373 { | 374 { |
374 base::AutoLock lock(g_lazy_child_thread_lock.Get()); | 375 base::AutoLock lock(g_lazy_child_thread_lock.Get()); |
375 g_child_thread = this; | 376 g_child_thread = this; |
| 377 g_child_thread_initialized = true; |
376 } | 378 } |
377 // Signalling without locking is fine here because only | 379 // Signalling without locking is fine here because only |
378 // one thread can wait on the condition variable. | 380 // one thread can wait on the condition variable. |
379 g_lazy_child_thread_cv.Get().Signal(); | 381 g_lazy_child_thread_cv.Get().Signal(); |
380 #endif | 382 #endif |
381 | 383 |
382 #if defined(TCMALLOC_TRACE_MEMORY_SUPPORTED) | 384 #if defined(TCMALLOC_TRACE_MEMORY_SUPPORTED) |
383 trace_memory_controller_.reset(new base::trace_event::TraceMemoryController( | 385 trace_memory_controller_.reset(new base::trace_event::TraceMemoryController( |
384 message_loop_->message_loop_proxy(), ::HeapProfilerWithPseudoStackStart, | 386 message_loop_->message_loop_proxy(), ::HeapProfilerWithPseudoStackStart, |
385 ::HeapProfilerStop, ::GetHeapProfile)); | 387 ::HeapProfilerStop, ::GetHeapProfile)); |
386 #endif | 388 #endif |
387 | 389 |
388 shared_bitmap_manager_.reset( | 390 shared_bitmap_manager_.reset( |
389 new ChildSharedBitmapManager(thread_safe_sender())); | 391 new ChildSharedBitmapManager(thread_safe_sender())); |
390 | 392 |
391 gpu_memory_buffer_manager_.reset( | 393 gpu_memory_buffer_manager_.reset( |
392 new ChildGpuMemoryBufferManager(thread_safe_sender())); | 394 new ChildGpuMemoryBufferManager(thread_safe_sender())); |
393 | 395 |
394 discardable_shared_memory_manager_.reset( | 396 discardable_shared_memory_manager_.reset( |
395 new ChildDiscardableSharedMemoryManager(thread_safe_sender())); | 397 new ChildDiscardableSharedMemoryManager(thread_safe_sender())); |
396 } | 398 } |
397 | 399 |
398 ChildThreadImpl::~ChildThreadImpl() { | 400 ChildThreadImpl::~ChildThreadImpl() { |
| 401 #if defined(OS_ANDROID) |
| 402 { |
| 403 base::AutoLock lock(g_lazy_child_thread_lock.Get()); |
| 404 g_child_thread = nullptr; |
| 405 } |
| 406 #endif |
| 407 |
399 #ifdef IPC_MESSAGE_LOG_ENABLED | 408 #ifdef IPC_MESSAGE_LOG_ENABLED |
400 IPC::Logging::GetInstance()->SetIPCSender(NULL); | 409 IPC::Logging::GetInstance()->SetIPCSender(NULL); |
401 #endif | 410 #endif |
402 | 411 |
403 channel_->RemoveFilter(histogram_message_filter_.get()); | 412 channel_->RemoveFilter(histogram_message_filter_.get()); |
404 channel_->RemoveFilter(sync_message_filter_.get()); | 413 channel_->RemoveFilter(sync_message_filter_.get()); |
405 | 414 |
406 // The ChannelProxy object caches a pointer to the IPC thread, so need to | 415 // The ChannelProxy object caches a pointer to the IPC thread, so need to |
407 // reset it as it's not guaranteed to outlive this object. | 416 // reset it as it's not guaranteed to outlive this object. |
408 // NOTE: this also has the side-effect of not closing the main IPC channel to | 417 // NOTE: this also has the side-effect of not closing the main IPC channel to |
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
592 } | 601 } |
593 | 602 |
594 #if defined(OS_ANDROID) | 603 #if defined(OS_ANDROID) |
595 // The method must NOT be called on the child thread itself. | 604 // The method must NOT be called on the child thread itself. |
596 // It may block the child thread if so. | 605 // It may block the child thread if so. |
597 void ChildThreadImpl::ShutdownThread() { | 606 void ChildThreadImpl::ShutdownThread() { |
598 DCHECK(!ChildThreadImpl::current()) << | 607 DCHECK(!ChildThreadImpl::current()) << |
599 "this method should NOT be called from child thread itself"; | 608 "this method should NOT be called from child thread itself"; |
600 { | 609 { |
601 base::AutoLock lock(g_lazy_child_thread_lock.Get()); | 610 base::AutoLock lock(g_lazy_child_thread_lock.Get()); |
602 while (!g_child_thread) | 611 while (!g_child_thread_initialized) |
603 g_lazy_child_thread_cv.Get().Wait(); | 612 g_lazy_child_thread_cv.Get().Wait(); |
| 613 |
| 614 // g_child_thread may already have been destructed while we didn't hold the |
| 615 // lock. |
| 616 if (!g_child_thread) |
| 617 return; |
| 618 |
| 619 DCHECK_NE(base::MessageLoop::current(), g_child_thread->message_loop()); |
| 620 g_child_thread->message_loop()->PostTask( |
| 621 FROM_HERE, base::Bind(&QuitMainThreadMessageLoop)); |
604 } | 622 } |
605 DCHECK_NE(base::MessageLoop::current(), g_child_thread->message_loop()); | |
606 g_child_thread->message_loop()->PostTask( | |
607 FROM_HERE, base::Bind(&QuitMainThreadMessageLoop)); | |
608 } | 623 } |
609 #endif | 624 #endif |
610 | 625 |
611 void ChildThreadImpl::OnProcessFinalRelease() { | 626 void ChildThreadImpl::OnProcessFinalRelease() { |
612 if (on_channel_error_called_) { | 627 if (on_channel_error_called_) { |
613 base::MessageLoop::current()->Quit(); | 628 base::MessageLoop::current()->Quit(); |
614 return; | 629 return; |
615 } | 630 } |
616 | 631 |
617 // The child process shutdown sequence is a request response based mechanism, | 632 // The child process shutdown sequence is a request response based mechanism, |
(...skipping 12 matching lines...) Expand all Loading... |
630 | 645 |
631 void ChildThreadImpl::OnProcessBackgrounded(bool background) { | 646 void ChildThreadImpl::OnProcessBackgrounded(bool background) { |
632 // Set timer slack to maximum on main thread when in background. | 647 // Set timer slack to maximum on main thread when in background. |
633 base::TimerSlack timer_slack = base::TIMER_SLACK_NONE; | 648 base::TimerSlack timer_slack = base::TIMER_SLACK_NONE; |
634 if (background) | 649 if (background) |
635 timer_slack = base::TIMER_SLACK_MAXIMUM; | 650 timer_slack = base::TIMER_SLACK_MAXIMUM; |
636 base::MessageLoop::current()->SetTimerSlack(timer_slack); | 651 base::MessageLoop::current()->SetTimerSlack(timer_slack); |
637 } | 652 } |
638 | 653 |
639 } // namespace content | 654 } // namespace content |
OLD | NEW |