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

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: Fixed issues with the 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 DBThreadBlocker() {
Nicolas Zea 2014/10/17 00:04:01 nit: I think it would be clearer to call this meth
stanisc 2014/10/17 06:58:02 Done.
262 EXPECT_FALSE(ui_thread_lock_.Try());
263
264 blocked_.Signal();
265 base::AutoLock l(ui_thread_lock_);
266 }
267
268 // Wrap SyncBackendRegistrar so that we can monitor its lifetime.
269 class TestRegistrar : public SyncBackendRegistrar {
Nicolas Zea 2014/10/17 00:04:01 nit: The usual style is to avoid nested classes li
stanisc 2014/10/17 06:58:02 Well, nested classes are supposed to be used for s
270 public:
271 explicit TestRegistrar(Profile* profile,
272 SyncBackendRegistrarShutdownTest* test)
273 : SyncBackendRegistrar("test", profile, scoped_ptr<base::Thread>()),
274 test_(test) {}
275
276 virtual ~TestRegistrar() { test_->registrar_destroyed_.Signal(); }
277
278 private:
279 SyncBackendRegistrarShutdownTest* test_;
280 };
281
282 protected:
283 SyncBackendRegistrarShutdownTest()
284 : thread_bundle_(content::TestBrowserThreadBundle::REAL_DB_THREAD |
285 content::TestBrowserThreadBundle::REAL_FILE_THREAD |
286 content::TestBrowserThreadBundle::REAL_IO_THREAD),
287 blocked_(false, false),
288 registrar_destroyed_(false, false) {}
289
290 virtual ~SyncBackendRegistrarShutdownTest() {}
291
292 content::TestBrowserThreadBundle thread_bundle_;
293 base::WaitableEvent blocked_;
Nicolas Zea 2014/10/17 00:04:01 nit: perhaps name this db_thread_blocked_
stanisc 2014/10/17 06:58:02 Done.
294 base::Lock ui_thread_lock_;
295 base::WaitableEvent registrar_destroyed_;
296 };
297
298 TEST_F(SyncBackendRegistrarShutdownTest, BlockingShutdown) {
299 // Lock |ui_thread_lock_| so that the DB thread can't acquire it.
Nicolas Zea 2014/10/17 00:04:01 nit: because the ui_thread_lock_ is actually being
stanisc 2014/10/17 06:58:02 Agree! Done.
300 ui_thread_lock_.Acquire();
301
302 // Block the DB thread by waiting on |ui_thread_lock_|.
303 BrowserThread::PostTask(
304 BrowserThread::DB,
305 FROM_HERE,
306 base::Bind(&SyncBackendRegistrarShutdownTest::DBThreadBlocker,
307 base::Unretained(this)));
308
309 TestingProfile profile;
310 scoped_ptr<TestRegistrar> registrar(new TestRegistrar(&profile, this));
311 base::Thread* sync_thread = registrar->sync_thread();
312
313 // Stop here until the DB thread gets a chance to run and block on the lock.
314 // Please note that since the task above didn't finish, the task to
315 // initialize the worker on the DB thread hasn't had a chance to run yet too.
316 // Which means ModelSafeWorker::SetWorkingLoopToCurrent hasn't been called
317 // for the DB worker.
318 blocked_.Wait();
319
320 registrar->SetInitialTypes(ModelTypeSet());
321
322 // Start the shutdown.
323 registrar->RequestWorkerStopOnUIThread();
324 sync_thread->message_loop()->PostTask(
325 FROM_HERE,
326 base::Bind(&SyncBackendRegistrar::Shutdown,
327 base::Unretained(registrar.release())));
328
329 // The test verifies that the sync thread doesn't block because
330 // of the blocked DB thread and can finish the shutdown.
331 sync_thread->message_loop()->RunUntilIdle();
332
333 ui_thread_lock_.Release();
334
335 // BrowserThread::UnsafeGetMessageLoopForThread(BrowserThread::DB)->
336 // RunUntilIdle();
Nicolas Zea 2014/10/17 00:04:01 did you mean to keep this around?
stanisc 2014/10/17 06:58:02 I ended up not needing this. Removed.
337
338 base::MessageLoop::current()->RunUntilIdle();
339
340 // This verifies that all workers have been removed and the registrar
341 // destroyed.
342 registrar_destroyed_.Wait();
343 }
344
259 } // namespace 345 } // namespace
260 346
261 } // namespace browser_sync 347 } // namespace browser_sync
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698