Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(66)

Side by Side Diff: content/child/child_thread_impl.cc

Issue 913203004: Clean up Android dangling g_child_thread pointer on shutdown. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Change comment text to address previous code review feedback Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698