Index: content/child/child_thread_impl.cc |
diff --git a/content/child/child_thread_impl.cc b/content/child/child_thread_impl.cc |
index d5d7a3d2589736b8d60225e710ed193d3fe2565e..55686062938b64308c01645f7b423514418ed28d 100644 |
--- a/content/child/child_thread_impl.cc |
+++ b/content/child/child_thread_impl.cc |
@@ -161,18 +161,19 @@ class SuicideOnChannelErrorFilter : public IPC::MessageFilter { |
#if defined(OS_ANDROID) |
ChildThreadImpl* g_child_thread = NULL; |
+bool g_child_thread_initialized = false; |
// A lock protects g_child_thread. |
-base::LazyInstance<base::Lock> g_lazy_child_thread_lock = |
+base::LazyInstance<base::Lock>::Leaky g_lazy_child_thread_lock = |
LAZY_INSTANCE_INITIALIZER; |
// base::ConditionVariable has an explicit constructor that takes |
// a base::Lock pointer as parameter. The base::DefaultLazyInstanceTraits |
// doesn't handle the case. Thus, we need our own class here. |
struct CondVarLazyInstanceTraits { |
- static const bool kRegisterOnExit = true; |
+ static const bool kRegisterOnExit = false; |
#ifndef NDEBUG |
- static const bool kAllowedToAccessOnNonjoinableThread = false; |
+ static const bool kAllowedToAccessOnNonjoinableThread = true; |
#endif |
static base::ConditionVariable* New(void* instance) { |
@@ -373,6 +374,7 @@ void ChildThreadImpl::Init(const Options& options) { |
{ |
base::AutoLock lock(g_lazy_child_thread_lock.Get()); |
g_child_thread = this; |
+ g_child_thread_initialized = true; |
} |
// Signalling without locking is fine here because only |
// one thread can wait on the condition variable. |
@@ -396,6 +398,13 @@ void ChildThreadImpl::Init(const Options& options) { |
} |
ChildThreadImpl::~ChildThreadImpl() { |
+#if defined(OS_ANDROID) |
+ { |
+ base::AutoLock lock(g_lazy_child_thread_lock.Get()); |
+ g_child_thread = nullptr; |
+ } |
+#endif |
+ |
#ifdef IPC_MESSAGE_LOG_ENABLED |
IPC::Logging::GetInstance()->SetIPCSender(NULL); |
#endif |
@@ -599,12 +608,18 @@ void ChildThreadImpl::ShutdownThread() { |
"this method should NOT be called from child thread itself"; |
{ |
base::AutoLock lock(g_lazy_child_thread_lock.Get()); |
- while (!g_child_thread) |
+ while (!g_child_thread_initialized) |
g_lazy_child_thread_cv.Get().Wait(); |
+ |
+ // g_child_thread may already have been destructed while we didn't hold the |
+ // lock. |
+ if (!g_child_thread) |
+ return; |
+ |
+ DCHECK_NE(base::MessageLoop::current(), g_child_thread->message_loop()); |
+ g_child_thread->message_loop()->PostTask( |
+ FROM_HERE, base::Bind(&QuitMainThreadMessageLoop)); |
} |
- DCHECK_NE(base::MessageLoop::current(), g_child_thread->message_loop()); |
- g_child_thread->message_loop()->PostTask( |
- FROM_HERE, base::Bind(&QuitMainThreadMessageLoop)); |
} |
#endif |