Chromium Code Reviews| 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> g_lazy_child_thread_lock = |
|
no sievers
2015/02/18 20:48:30
base::LazyInstance<base::Lock>::Leaky
aelias_OOO_until_Jul13
2015/02/19 01:00:28
Done.
| |
| 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 = true; |
|
no sievers
2015/02/18 20:48:30
kRegisterOnExit = false;
should have the same eff
aelias_OOO_until_Jul13
2015/02/19 01:00:28
OK, set to "false". I stayed with the traits to k
| |
| 174 #ifndef NDEBUG | 175 #ifndef NDEBUG |
| 175 static const bool kAllowedToAccessOnNonjoinableThread = false; | 176 static const bool kAllowedToAccessOnNonjoinableThread = false; |
|
no sievers
2015/02/18 20:48:30
Hmm, this might be wrong too since the thread we c
aelias_OOO_until_Jul13
2015/02/19 01:00:28
Changed to "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 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 591 return g_lazy_tls.Pointer()->Get(); | 600 return g_lazy_tls.Pointer()->Get(); |
| 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()); |
|
no sievers
2015/02/18 19:19:42
What about the two lazy instances (lock and cv), c
aelias_OOO_until_Jul13
2015/02/18 19:37:27
One hint FWIW is that this is a preexisting proble
no sievers
2015/02/18 20:48:30
I think it's wrong that we access the lazy instanc
aelias_OOO_until_Jul13
2015/02/19 01:00:28
Done.
| |
| 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 elsewhere. | |
|
no sievers
2015/02/18 19:19:42
nit: "...may already have been destructed while we
| |
| 615 if (!g_child_thread) | |
| 616 return; | |
|
Feng Qian
2015/02/18 01:47:32
Seems that only path to get here is that ChildThre
aelias_OOO_until_Jul13
2015/02/18 02:46:52
As discussed offline, ~ChildThreadImpl is called f
| |
| 617 | |
| 618 DCHECK_NE(base::MessageLoop::current(), g_child_thread->message_loop()); | |
| 619 g_child_thread->message_loop()->PostTask( | |
| 620 FROM_HERE, base::Bind(&QuitMainThreadMessageLoop)); | |
| 604 } | 621 } |
| 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 } | 622 } |
| 609 #endif | 623 #endif |
| 610 | 624 |
| 611 void ChildThreadImpl::OnProcessFinalRelease() { | 625 void ChildThreadImpl::OnProcessFinalRelease() { |
| 612 if (on_channel_error_called_) { | 626 if (on_channel_error_called_) { |
| 613 base::MessageLoop::current()->Quit(); | 627 base::MessageLoop::current()->Quit(); |
| 614 return; | 628 return; |
| 615 } | 629 } |
| 616 | 630 |
| 617 // The child process shutdown sequence is a request response based mechanism, | 631 // The child process shutdown sequence is a request response based mechanism, |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 630 | 644 |
| 631 void ChildThreadImpl::OnProcessBackgrounded(bool background) { | 645 void ChildThreadImpl::OnProcessBackgrounded(bool background) { |
| 632 // Set timer slack to maximum on main thread when in background. | 646 // Set timer slack to maximum on main thread when in background. |
| 633 base::TimerSlack timer_slack = base::TIMER_SLACK_NONE; | 647 base::TimerSlack timer_slack = base::TIMER_SLACK_NONE; |
| 634 if (background) | 648 if (background) |
| 635 timer_slack = base::TIMER_SLACK_MAXIMUM; | 649 timer_slack = base::TIMER_SLACK_MAXIMUM; |
| 636 base::MessageLoop::current()->SetTimerSlack(timer_slack); | 650 base::MessageLoop::current()->SetTimerSlack(timer_slack); |
| 637 } | 651 } |
| 638 | 652 |
| 639 } // namespace content | 653 } // namespace content |
| OLD | NEW |