From 415c0108dcc2db461cf46a6692a27fbf0c36ded8 Mon Sep 17 00:00:00 2001 From: "haitaol@chromium.org" Date: Wed, 21 Aug 2013 04:51:26 +0000 Subject: Null ModelSafeWorker's working_loop_ if loop is destructed and synchronize access to workiing_loop_. Otherwise ModelSafeWorker could try to unregister for dead loop. BUG=274729 Review URL: https://chromiumcodereview.appspot.com/22985008 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@218648 0039d316-1c4b-4281-b951-d872f2087c98 --- .../public/engine/model_safe_worker.cc | 32 ++++++++++++++++------ .../internal_api/public/engine/model_safe_worker.h | 1 + 2 files changed, 25 insertions(+), 8 deletions(-) (limited to 'sync') diff --git a/sync/internal_api/public/engine/model_safe_worker.cc b/sync/internal_api/public/engine/model_safe_worker.cc index 7179ed5..5c91715 100644 --- a/sync/internal_api/public/engine/model_safe_worker.cc +++ b/sync/internal_api/public/engine/model_safe_worker.cc @@ -134,11 +134,17 @@ void ModelSafeWorker::WillDestroyCurrentMessageLoop() { << " worker stops on destruction of its working thread."; } + { + base::AutoLock l(working_loop_lock_); + working_loop_ = NULL; + } + if (observer_) observer_->OnWorkerLoopDestroyed(GetModelSafeGroup()); } void ModelSafeWorker::SetWorkingLoopToCurrent() { + base::AutoLock l(working_loop_lock_); DCHECK(!working_loop_); working_loop_ = base::MessageLoop::current(); working_loop_set_wait_.Signal(); @@ -150,19 +156,29 @@ void ModelSafeWorker::UnregisterForLoopDestruction( // loop. working_loop_set_wait_.Wait(); - // Should be called on sync loop. - DCHECK_NE(base::MessageLoop::current(), working_loop_); - DCHECK(working_loop_); - working_loop_->PostTask( - FROM_HERE, - base::Bind(&ModelSafeWorker::UnregisterForLoopDestructionAsync, - this, unregister_done_callback)); + { + base::AutoLock l(working_loop_lock_); + if (working_loop_ != NULL) { + // Should be called on sync loop. + DCHECK_NE(base::MessageLoop::current(), working_loop_); + working_loop_->PostTask( + FROM_HERE, + base::Bind(&ModelSafeWorker::UnregisterForLoopDestructionAsync, + this, unregister_done_callback)); + } + } } void ModelSafeWorker::UnregisterForLoopDestructionAsync( base::Callback unregister_done_callback) { + { + base::AutoLock l(working_loop_lock_); + if (!working_loop_) + return; + DCHECK_EQ(base::MessageLoop::current(), working_loop_); + } + DCHECK(stopped_); - DCHECK_EQ(base::MessageLoop::current(), working_loop_); base::MessageLoop::current()->RemoveDestructionObserver(this); unregister_done_callback.Run(GetModelSafeGroup()); } diff --git a/sync/internal_api/public/engine/model_safe_worker.h b/sync/internal_api/public/engine/model_safe_worker.h index f6b7ea6..0f41594 100644 --- a/sync/internal_api/public/engine/model_safe_worker.h +++ b/sync/internal_api/public/engine/model_safe_worker.h @@ -132,6 +132,7 @@ class SYNC_EXPORT ModelSafeWorker // Remember working loop for posting task to unregister destruction // observation from sync thread when shutting down sync. + base::Lock working_loop_lock_; base::MessageLoop* working_loop_; base::WaitableEvent working_loop_set_wait_; }; -- cgit v1.1