• rdevlin.cronin's avatar
    Revert "Sync: Avoid deadlock in SyncBackendRegistrar / ModelSafeWorker on sync backend shutdown." · 141df6d1
    rdevlin.cronin authored
    This reverts commit 8e84bfcc.
    
    Original CL: https://codereview.chromium.org/637413003
    Reason for Revert:
    New test SyncBackendRegistrarShutdownTest.BlockingShutdown fails repeatedly
    on android and causes other tests to hang.
    Also fails on other bots.
    http://chromium-build-logs.appspot.com/gtest_query?gtest_query=SyncBackendRegistrarShutdownTest.BlockingShutdown
    Failures are timeouts, and don't have any useful logs or stack traces (sorry).
    
    Reason for hand-revert: Conflict with crrev.com/0cd9ff92
    
    NOTRY=true
    TBR=stanisc@chromium.org
    TBR=zea@chromium.org
    
    -- Original CL Description --
    
    Sync: Avoid deadlock in SyncBackendRegistrar / ModelSafeWorker on sync backend shutdown.
    
    This deadlock involves SyncBackendRegistrar running on the sync thread and at least two
    workers - one of them (worker A) running on UI thread and
    another (worker B) running on some other background thread.
    In this particular case it was a password worker running on Password model thread.
    
    The deadlock occurs when the SyncBackendRegistrar shutdown
    code running in the sync thread blocks on a waitable event
    set by worker B, at the same time the worker B's thread is
    blocked for whatever reason waiting to make a synchronous
    call into the UI thread, and at the same time the worker A
    is blocked on a lock owned by the sync thread while it attempts
    to unregister itself with SyncBackendRegistrar.
    
    I think the main issue here is that the sync thread might
    block on a worker. This is possible in only one situation -
    when that worker hasn't have a chance to run any tasks because
    its own thread was blocked doing something else.
    
    The fix removes this dependency. The only reason this
    blocking occurs is because ModelSafeWorker has a mechanism
    for subscribing / unsubscribing to the MessageLoop descruction
    which has to be done in the right thread context.
    In order to unsubscribe the worker needs to remember the message loop it runs on which is done
    in SetWorkingLoopToCurrent callback, which is called from a task
    posted on the worker's thread. There is also a waitable
    event which is signalled at that time. The even is used to
    block ModelSafeWorker::UnregisterForLoopDestruction from
    delegating the call on an uninitialized message loop which
    is possible only when SetWorkingLoopToCurrent has never been called.
    
    There is no need to block in UnregisterForLoopDestruction.
    If the registration for even loop destruction hasn't been
    been done yet (because the thread is blocked) then there
    really no reason to wait for that and then immediately
    unsubscribe. We can skip both subscription to the even loop
    notification altogether and let the registrar know that
    it is OK to remove the worker. That's essentially what the
    fix does.
    
    I added a test that verifies that SyncBackendRegistrar::Shutdown
    doesn't block on a blocked model type thread anymore.
    
    BUG=423078
    Committed: https://crrev.com/8e84bfcc1c33fc0b63392d48ee8288d73f4a7675
    Cr-Commit-Position: refs/heads/master@{#300350}
    
    Review URL: https://codereview.chromium.org/667573007
    
    Cr-Commit-Position: refs/heads/master@{#300498}
    141df6d1
sync_backend_registrar_unittest.cc 9.45 KB