Index: sync/engine/net/server_connection_manager.cc |
diff --git a/sync/engine/net/server_connection_manager.cc b/sync/engine/net/server_connection_manager.cc |
index 0076543374fcdcedae2a86bfe62f2a1491ecb5e0..a54c9754253f0883fdac1e9fb14e845e958eaba9 100644 |
--- a/sync/engine/net/server_connection_manager.cc |
+++ b/sync/engine/net/server_connection_manager.cc |
@@ -16,6 +16,7 @@ |
#include "net/http/http_status_code.h" |
#include "sync/engine/net/url_translator.h" |
#include "sync/engine/syncer.h" |
+#include "sync/internal_api/public/base/cancelation_signal.h" |
#include "sync/protocol/sync.pb.h" |
#include "sync/syncable/directory.h" |
#include "url/gurl.h" |
@@ -114,13 +115,32 @@ bool ServerConnectionManager::Connection::ReadDownloadResponse( |
} |
ServerConnectionManager::ScopedConnectionHelper::ScopedConnectionHelper( |
- ServerConnectionManager* manager, Connection* connection) |
- : manager_(manager), connection_(connection) {} |
+ CancelationSignal* signaller, scoped_ptr<Connection> connection) |
+ : cancelation_signal_(signaller), connection_(connection.Pass()) { |
+ // Special early return for tests. |
+ if (!connection_.get()) |
+ return; |
+ |
+ if (!cancelation_signal_->TryRegisterHandler(this)) { |
+ connection_.reset(); |
+ } |
+} |
+ |
+// This function may be called from another thread. |
+void ServerConnectionManager::ScopedConnectionHelper::OnStopRequested() { |
+ DCHECK(connection_); |
+ connection_->Abort(); |
+} |
ServerConnectionManager::ScopedConnectionHelper::~ScopedConnectionHelper() { |
- if (connection_) |
- manager_->OnConnectionDestroyed(connection_.get()); |
- connection_.reset(); |
+ // We should be registered iff connection_.get() != NULL. |
+ if (connection_.get()) { |
+ // It is important that this be called before this destructor completes. |
+ // Until the unregistration is complete, it's possible that the virtual |
+ // OnStopRequested() function may be called from a different thread. We |
+ // need to unregister it before destruction modifies our vptr. |
+ cancelation_signal_->UnregisterHandler(this); |
+ } |
} |
ServerConnectionManager::Connection* |
@@ -177,43 +197,20 @@ ServerConnectionManager::ServerConnectionManager( |
const string& server, |
int port, |
bool use_ssl, |
- bool use_oauth2_token) |
+ bool use_oauth2_token, |
+ CancelationSignal* cancelation_signal) |
: sync_server_(server), |
sync_server_port_(port), |
use_ssl_(use_ssl), |
use_oauth2_token_(use_oauth2_token), |
proto_sync_path_(kSyncServerSyncPath), |
server_status_(HttpResponse::NONE), |
- terminated_(false), |
- active_connection_(NULL) { |
+ cancelation_signal_(cancelation_signal) { |
} |
ServerConnectionManager::~ServerConnectionManager() { |
} |
-ServerConnectionManager::Connection* |
-ServerConnectionManager::MakeActiveConnection() { |
- base::AutoLock lock(terminate_connection_lock_); |
- DCHECK(!active_connection_); |
- if (terminated_) |
- return NULL; |
- |
- active_connection_ = MakeConnection(); |
- return active_connection_; |
-} |
- |
-void ServerConnectionManager::OnConnectionDestroyed(Connection* connection) { |
- DCHECK(connection); |
- base::AutoLock lock(terminate_connection_lock_); |
- // |active_connection_| can be NULL already if it was aborted. Also, |
- // it can legitimately be a different Connection object if a new Connection |
- // was created after a previous one was Aborted and destroyed. |
- if (active_connection_ != connection) |
- return; |
- |
- active_connection_ = NULL; |
-} |
- |
bool ServerConnectionManager::SetAuthToken(const std::string& auth_token) { |
DCHECK(thread_checker_.CalledOnValidThread()); |
if (previously_invalidated_token != auth_token) { |
@@ -278,7 +275,7 @@ bool ServerConnectionManager::PostBufferToPath(PostBufferParams* params, |
// When our connection object falls out of scope, it clears itself from |
// active_connection_. |
- ScopedConnectionHelper post(this, MakeActiveConnection()); |
+ ScopedConnectionHelper post(cancelation_signal_, MakeConnection()); |
if (!post.get()) { |
params->response.server_status = HttpResponse::CONNECTION_UNAVAILABLE; |
return false; |
@@ -343,20 +340,10 @@ void ServerConnectionManager::RemoveListener( |
listeners_.RemoveObserver(listener); |
} |
-ServerConnectionManager::Connection* ServerConnectionManager::MakeConnection() |
+scoped_ptr<ServerConnectionManager::Connection> |
+ServerConnectionManager::MakeConnection() |
{ |
- return NULL; // For testing. |
-} |
- |
-void ServerConnectionManager::TerminateAllIO() { |
- base::AutoLock lock(terminate_connection_lock_); |
- terminated_ = true; |
- if (active_connection_) |
- active_connection_->Abort(); |
- |
- // Sever our ties to this connection object. Note that it still may exist, |
- // since we don't own it, but it has been neutered. |
- active_connection_ = NULL; |
+ return scoped_ptr<Connection>(); // For testing. |
} |
std::ostream& operator << (std::ostream& s, const struct HttpResponse& hr) { |