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

Side by Side Diff: chrome/browser/sync/glue/sync_backend_registrar_unittest.cc

Issue 640853008: Sync: Avoid deadlock in SyncBackendRegistrar / ModelSafeWorker on sync backend shutdown. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fixed linux_clang_tsan warning about lock-order-inversion Created 6 years, 2 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
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 "chrome/browser/sync/glue/sync_backend_registrar.h" 5 #include "chrome/browser/sync/glue/sync_backend_registrar.h"
6 6
7 #include "base/run_loop.h"
7 #include "chrome/browser/sync/glue/ui_model_worker.h" 8 #include "chrome/browser/sync/glue/ui_model_worker.h"
8 #include "chrome/test/base/testing_profile.h" 9 #include "chrome/test/base/testing_profile.h"
9 #include "components/sync_driver/change_processor_mock.h" 10 #include "components/sync_driver/change_processor_mock.h"
10 #include "content/public/browser/browser_thread.h" 11 #include "content/public/browser/browser_thread.h"
11 #include "content/public/test/test_browser_thread_bundle.h" 12 #include "content/public/test/test_browser_thread_bundle.h"
12 #include "sync/internal_api/public/base/model_type.h" 13 #include "sync/internal_api/public/base/model_type.h"
13 #include "sync/internal_api/public/test/test_user_share.h" 14 #include "sync/internal_api/public/test/test_user_share.h"
14 #include "testing/gmock/include/gmock/gmock.h" 15 #include "testing/gmock/include/gmock/gmock.h"
15 #include "testing/gtest/include/gtest/gtest.h" 16 #include "testing/gtest/include/gtest/gtest.h"
16 17
(...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after
249 done.Wait(); 250 done.Wait();
250 251
251 registrar_->DeactivateDataType(AUTOFILL); 252 registrar_->DeactivateDataType(AUTOFILL);
252 ExpectRoutingInfo(registrar_.get(), syncer::ModelSafeRoutingInfo()); 253 ExpectRoutingInfo(registrar_.get(), syncer::ModelSafeRoutingInfo());
253 ExpectHasProcessorsForTypes(*registrar_, ModelTypeSet()); 254 ExpectHasProcessorsForTypes(*registrar_, ModelTypeSet());
254 255
255 // Should do nothing. 256 // Should do nothing.
256 TriggerChanges(registrar_.get(), AUTOFILL); 257 TriggerChanges(registrar_.get(), AUTOFILL);
257 } 258 }
258 259
260 class SyncBackendRegistrarShutdownTest : public testing::Test {
261 public:
262 void BlockDBThread() {
263 EXPECT_FALSE(db_thread_lock_.Try());
264
265 db_thread_blocked_.Signal();
266 base::AutoLock l(db_thread_lock_);
267 }
268
269 protected:
270 friend class TestRegistrar;
271
272 SyncBackendRegistrarShutdownTest()
273 : thread_bundle_(content::TestBrowserThreadBundle::REAL_DB_THREAD |
274 content::TestBrowserThreadBundle::REAL_FILE_THREAD |
275 content::TestBrowserThreadBundle::REAL_IO_THREAD),
276 db_thread_blocked_(false, false) {
277 quit_closure_ = run_loop_.QuitClosure();
278 }
279
280 virtual ~SyncBackendRegistrarShutdownTest() {}
281
282 void PostQuitOnUIMessageLoop() {
283 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, quit_closure_);
284 }
285
286 content::TestBrowserThreadBundle thread_bundle_;
287 TestingProfile profile_;
288 base::WaitableEvent db_thread_blocked_;
289 base::Lock db_thread_lock_;
290 base::RunLoop run_loop_;
291 base::Closure quit_closure_;
292 };
293
294 // Wrap SyncBackendRegistrar so that we can monitor its lifetime.
295 class TestRegistrar : public SyncBackendRegistrar {
296 public:
297 explicit TestRegistrar(Profile* profile,
298 SyncBackendRegistrarShutdownTest* test)
299 : SyncBackendRegistrar("test", profile, scoped_ptr<base::Thread>()),
300 test_(test) {}
301
302 ~TestRegistrar() override { test_->PostQuitOnUIMessageLoop(); }
303
304 private:
305 SyncBackendRegistrarShutdownTest* test_;
306 };
307
308 TEST_F(SyncBackendRegistrarShutdownTest, BlockingShutdown) {
309 // Take ownership of |db_thread_lock_| so that the DB thread can't acquire it.
310 db_thread_lock_.Acquire();
311
312 // This will block the DB thread by waiting on |db_thread_lock_|.
313 BrowserThread::PostTask(
314 BrowserThread::DB,
315 FROM_HERE,
316 base::Bind(&SyncBackendRegistrarShutdownTest::BlockDBThread,
317 base::Unretained(this)));
318
319 scoped_ptr<TestRegistrar> registrar(new TestRegistrar(&profile_, this));
320 base::Thread* sync_thread = registrar->sync_thread();
321
322 // Stop here until the DB thread gets a chance to run and block on the lock.
323 // Please note that since the task above didn't finish, the task to
324 // initialize the worker on the DB thread hasn't had a chance to run yet too.
325 // Which means ModelSafeWorker::SetWorkingLoopToCurrent hasn't been called
326 // for the DB worker.
327 db_thread_blocked_.Wait();
328
329 registrar->SetInitialTypes(ModelTypeSet());
330
331 // Start the shutdown.
332 registrar->RequestWorkerStopOnUIThread();
333
334 sync_thread->message_loop()->PostTask(
335 FROM_HERE,
336 base::Bind(&SyncBackendRegistrar::Shutdown,
337 base::Unretained(registrar.release())));
338
339 // The test verifies that the sync thread doesn't block because
340 // of the blocked DB thread and can finish the shutdown.
341 sync_thread->message_loop()->RunUntilIdle();
342
343 db_thread_lock_.Release();
344
345 // Run the main thread loop until all workers have been removed and the
346 // registrar destroyed.
347 run_loop_.Run();
348 }
349
259 } // namespace 350 } // namespace
260 351
261 } // namespace browser_sync 352 } // namespace browser_sync
OLDNEW
« no previous file with comments | « chrome/browser/sync/glue/password_model_worker.cc ('k') | chrome/browser/sync/glue/ui_model_worker.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698