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

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 hang in the unit test 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 "chrome/browser/sync/glue/ui_model_worker.h" 7 #include "chrome/browser/sync/glue/ui_model_worker.h"
8 #include "chrome/test/base/testing_profile.h" 8 #include "chrome/test/base/testing_profile.h"
9 #include "components/sync_driver/change_processor_mock.h" 9 #include "components/sync_driver/change_processor_mock.h"
10 #include "content/public/browser/browser_thread.h" 10 #include "content/public/browser/browser_thread.h"
(...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after
249 done.Wait(); 249 done.Wait();
250 250
251 registrar_->DeactivateDataType(AUTOFILL); 251 registrar_->DeactivateDataType(AUTOFILL);
252 ExpectRoutingInfo(registrar_.get(), syncer::ModelSafeRoutingInfo()); 252 ExpectRoutingInfo(registrar_.get(), syncer::ModelSafeRoutingInfo());
253 ExpectHasProcessorsForTypes(*registrar_, ModelTypeSet()); 253 ExpectHasProcessorsForTypes(*registrar_, ModelTypeSet());
254 254
255 // Should do nothing. 255 // Should do nothing.
256 TriggerChanges(registrar_.get(), AUTOFILL); 256 TriggerChanges(registrar_.get(), AUTOFILL);
257 } 257 }
258 258
259 class SyncBackendRegistrarShutdownTest : public testing::Test {
260 public:
261 void BlockDBThread() {
262 EXPECT_FALSE(db_thread_lock_.Try());
263
264 db_thread_blocked_.Signal();
265 base::AutoLock l(db_thread_lock_);
266 }
267
268 protected:
269 friend class TestRegistrar;
270
271 SyncBackendRegistrarShutdownTest()
272 : thread_bundle_(content::TestBrowserThreadBundle::REAL_DB_THREAD |
273 content::TestBrowserThreadBundle::REAL_FILE_THREAD |
274 content::TestBrowserThreadBundle::REAL_IO_THREAD),
275 db_thread_blocked_(false, false) {}
276
277 virtual ~SyncBackendRegistrarShutdownTest() {}
278
279 content::TestBrowserThreadBundle thread_bundle_;
280 base::WaitableEvent db_thread_blocked_;
281 base::Lock db_thread_lock_;
282 };
283
284 // Wrap SyncBackendRegistrar so that we can monitor its lifetime.
285 class TestRegistrar : public SyncBackendRegistrar {
286 public:
287 explicit TestRegistrar(Profile* profile)
288 : SyncBackendRegistrar("test", profile, scoped_ptr<base::Thread>()) {}
289
290 ~TestRegistrar() override {
291 BrowserThread::PostTask(
292 BrowserThread::UI, FROM_HERE, base::MessageLoop::QuitClosure());
293 }
294 };
295
296 TEST_F(SyncBackendRegistrarShutdownTest, BlockingShutdown) {
297 // Take ownership of |db_thread_lock_| so that the DB thread can't acquire it.
298 db_thread_lock_.Acquire();
299
300 // This will block the DB thread by waiting on |db_thread_lock_|.
301 BrowserThread::PostTask(
302 BrowserThread::DB,
303 FROM_HERE,
304 base::Bind(&SyncBackendRegistrarShutdownTest::BlockDBThread,
305 base::Unretained(this)));
306
307 TestingProfile profile;
308 scoped_ptr<TestRegistrar> registrar(new TestRegistrar(&profile));
309 base::Thread* sync_thread = registrar->sync_thread();
310
311 // Stop here until the DB thread gets a chance to run and block on the lock.
312 // Please note that since the task above didn't finish, the task to
313 // initialize the worker on the DB thread hasn't had a chance to run yet too.
314 // Which means ModelSafeWorker::SetWorkingLoopToCurrent hasn't been called
315 // for the DB worker.
316 db_thread_blocked_.Wait();
317
318 registrar->SetInitialTypes(ModelTypeSet());
319
320 // Start the shutdown.
321 registrar->RequestWorkerStopOnUIThread();
322
323 sync_thread->message_loop()->PostTask(
324 FROM_HERE,
325 base::Bind(&SyncBackendRegistrar::Shutdown,
326 base::Unretained(registrar.release())));
327
328 // The test verifies that the sync thread doesn't block because
329 // of the blocked DB thread and can finish the shutdown.
330 sync_thread->message_loop()->RunUntilIdle();
331
332 db_thread_lock_.Release();
333
334 // Run the main thread loop until all workers have been removed and the
335 // registrar destroyed.
336 base::MessageLoop::current()->Run();
Nicolas Zea 2014/10/22 17:06:44 nit: Run() is deprecated. The preferred approach t
stanisc 2014/10/23 17:51:13 Done.
337 }
338
259 } // namespace 339 } // namespace
260 340
261 } // namespace browser_sync 341 } // 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