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

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

Issue 637413003: Sync: Avoid deadlock in SyncBackendRegistrar / ModelSafeWorker on sync backend shutdown. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Minor tweaks 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 registrar_destroyed_(false, false) {}
277
278 virtual ~SyncBackendRegistrarShutdownTest() {}
279
280 content::TestBrowserThreadBundle thread_bundle_;
281 base::WaitableEvent db_thread_blocked_;
282 base::Lock db_thread_lock_;
283 base::WaitableEvent registrar_destroyed_;
284 };
285
286 // Wrap SyncBackendRegistrar so that we can monitor its lifetime.
287 class TestRegistrar : public SyncBackendRegistrar {
288 public:
289 explicit TestRegistrar(Profile* profile,
290 SyncBackendRegistrarShutdownTest* test)
291 : SyncBackendRegistrar("test", profile, scoped_ptr<base::Thread>()),
292 test_(test) {}
293
294 virtual ~TestRegistrar() { test_->registrar_destroyed_.Signal(); }
295
296 private:
297 SyncBackendRegistrarShutdownTest* test_;
298 };
299
300 TEST_F(SyncBackendRegistrarShutdownTest, BlockingShutdown) {
301 // Take ownership of |db_thread_lock_| so that the DB thread can't acquire it.
302 db_thread_lock_.Acquire();
303
304 // This will block the DB thread by waiting on |db_thread_lock_|.
305 BrowserThread::PostTask(
306 BrowserThread::DB,
307 FROM_HERE,
308 base::Bind(&SyncBackendRegistrarShutdownTest::BlockDBThread,
309 base::Unretained(this)));
310
311 TestingProfile profile;
312 scoped_ptr<TestRegistrar> registrar(new TestRegistrar(&profile, this));
313 base::Thread* sync_thread = registrar->sync_thread();
314
315 // Stop here until the DB thread gets a chance to run and block on the lock.
316 // Please note that since the task above didn't finish, the task to
317 // initialize the worker on the DB thread hasn't had a chance to run yet too.
318 // Which means ModelSafeWorker::SetWorkingLoopToCurrent hasn't been called
319 // for the DB worker.
320 db_thread_blocked_.Wait();
321
322 registrar->SetInitialTypes(ModelTypeSet());
323
324 // Start the shutdown.
325 registrar->RequestWorkerStopOnUIThread();
326 sync_thread->message_loop()->PostTask(
327 FROM_HERE,
328 base::Bind(&SyncBackendRegistrar::Shutdown,
329 base::Unretained(registrar.release())));
330
331 // The test verifies that the sync thread doesn't block because
332 // of the blocked DB thread and can finish the shutdown.
333 sync_thread->message_loop()->RunUntilIdle();
334
335 db_thread_lock_.Release();
336
337 base::MessageLoop::current()->RunUntilIdle();
338
339 // This verifies that all workers have been removed and the registrar
340 // destroyed.
341 registrar_destroyed_.Wait();
342 }
343
259 } // namespace 344 } // namespace
260 345
261 } // namespace browser_sync 346 } // 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