diff options
author | rlarocque@chromium.org <rlarocque@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-09-19 01:17:02 +0000 |
---|---|---|
committer | rlarocque@chromium.org <rlarocque@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-09-19 01:17:02 +0000 |
commit | ea29851b736ba58190146f5ce0bef59683ad8904 (patch) | |
tree | d5dea3dc7483b2d65601d87304b3282189f3dbb5 /sync/internal_api/http_bridge_unittest.cc | |
parent | 4f432a56da54cdbe213ae943944599072a690c75 (diff) | |
download | chromium_src-ea29851b736ba58190146f5ce0bef59683ad8904.zip chromium_src-ea29851b736ba58190146f5ce0bef59683ad8904.tar.gz chromium_src-ea29851b736ba58190146f5ce0bef59683ad8904.tar.bz2 |
sync: Gracefully handle early shutdown
Introduce a new object to communicate cross-thread cancellation signals.
This new object, the CancellationSignal, is protected by a lock. It
allows the receiving thread to query whether or not a stop has been
requested. It also allows the receiving thread to safely register a
cross-thread callback to be invoked immediately when a stop is
requested.
We use two instances of this class to ensure we meet all the
requirements for a safe and fast sync backend shutdown.
The first instance is used with the HttpBridgeFactory to allow the UI
thread to force it to drop all refereces to its RequestContextGetter
immediately. This is an important part of our plan to ensure that all
references to that object are released before
ProfileSyncService::Shutdown() returns, which is necessary to avoid
racy crashes at shutdown. (See crbug.com/236451)
The second instance is used with the ServerConnectionManager and the
Syncer. Once signalled, it ensures that any active connections are
released (possibly decrementing another ref to the
RequestContextGetter), that any blocking I/O is aborted, and that no
more connections will be instantiated. It's important to prevent the
creation of more connections because the HttpBridgeFactory might trigger
a crash if we asked it to create another connection after it had been
shut down.
The syncer's interaction with the second cancelation signal is more
passive. It does not execute any callbacks when the signal is sent.
Instead, it queries the signal as it performs sync cycles, and will cut
short any existing sync cycle if it notices the signal has been sent.
Finally, this CL includes one important change to the initialization of
the HttpBridgeFactory. In order to properly register with the
cancellation signal while still allowing the creation of the user agent
to occur on the sync thread, its initialization had to be split into two
parts. This class now has an Init() method in addition to its
constructor.
BUG=236451
Review URL: https://chromiumcodereview.appspot.com/23717047
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@224014 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'sync/internal_api/http_bridge_unittest.cc')
-rw-r--r-- | sync/internal_api/http_bridge_unittest.cc | 16 |
1 files changed, 11 insertions, 5 deletions
diff --git a/sync/internal_api/http_bridge_unittest.cc b/sync/internal_api/http_bridge_unittest.cc index 9cb37df..e1dc6de 100644 --- a/sync/internal_api/http_bridge_unittest.cc +++ b/sync/internal_api/http_bridge_unittest.cc @@ -9,6 +9,7 @@ #include "net/url_request/test_url_fetcher_factory.h" #include "net/url_request/url_fetcher_delegate.h" #include "net/url_request/url_request_test_util.h" +#include "sync/internal_api/public/base/cancelation_signal.h" #include "sync/internal_api/public/http_bridge.h" #include "testing/gtest/include/gtest/gtest.h" @@ -407,14 +408,16 @@ TEST_F(SyncHttpBridgeTest, AbortAndReleaseBeforeFetchComplete) { void HttpBridgeRunOnSyncThread( net::URLRequestContextGetter* baseline_context_getter, + CancelationSignal* factory_cancelation_signal, syncer::HttpPostProviderFactory** bridge_factory_out, syncer::HttpPostProviderInterface** bridge_out, base::WaitableEvent* signal_when_created, base::WaitableEvent* wait_for_shutdown) { - scoped_ptr<syncer::HttpPostProviderFactory> bridge_factory( + scoped_ptr<syncer::HttpBridgeFactory> bridge_factory( new syncer::HttpBridgeFactory(baseline_context_getter, - "test", - NetworkTimeUpdateCallback())); + NetworkTimeUpdateCallback(), + factory_cancelation_signal)); + bridge_factory->Init("test"); *bridge_factory_out = bridge_factory.get(); HttpPostProviderInterface* bridge = bridge_factory->Create(); @@ -447,18 +450,21 @@ TEST_F(SyncHttpBridgeTest, RequestContextGetterReleaseOrder) { base::WaitableEvent signal_when_created(false, false); base::WaitableEvent wait_for_shutdown(false, false); + CancelationSignal release_request_context_signal; + // Create bridge factory and factory on sync thread and wait for the creation // to finish. sync_thread.message_loop()->PostTask(FROM_HERE, base::Bind(&HttpBridgeRunOnSyncThread, base::Unretained(baseline_context_getter.get()), - &factory, &bridge, &signal_when_created, &wait_for_shutdown)); + &release_request_context_signal ,&factory, &bridge, + &signal_when_created, &wait_for_shutdown)); signal_when_created.Wait(); // Simulate sync shutdown by aborting bridge and shutting down factory on // frontend. bridge->Abort(); - factory->Shutdown(); + release_request_context_signal.Signal(); // Wait for sync's RequestContextGetter to be cleared on IO thread and // check for reference count. |