| Index: net/base/tcp_client_socket_pool.cc
|
| diff --git a/net/base/tcp_client_socket_pool.cc b/net/base/tcp_client_socket_pool.cc
|
| index d35c71a997bfa7ba1e73e88a87f5080ad387af4c..7dadd4cd4261761727b8fa9e3a0c33a6deabcd0c 100644
|
| --- a/net/base/tcp_client_socket_pool.cc
|
| +++ b/net/base/tcp_client_socket_pool.cc
|
| @@ -45,15 +45,20 @@ TCPClientSocketPool::ConnectingSocket::ConnectingSocket(
|
| callback_(this,
|
| &TCPClientSocketPool::ConnectingSocket::OnIOComplete)),
|
| pool_(pool),
|
| - resolver_(pool->GetHostResolver()) {}
|
| + resolver_(pool->GetHostResolver()),
|
| + canceled_(false) {
|
| + CHECK(!ContainsKey(pool_->connecting_socket_map_, handle));
|
| + pool_->connecting_socket_map_[handle] = this;
|
| +}
|
|
|
| TCPClientSocketPool::ConnectingSocket::~ConnectingSocket() {
|
| - // We don't worry about cancelling the host resolution and TCP connect, since
|
| - // ~SingleRequestHostResolver and ~ClientSocket will take care of it.
|
| + if (!canceled_)
|
| + pool_->connecting_socket_map_.erase(handle_);
|
| }
|
|
|
| int TCPClientSocketPool::ConnectingSocket::Connect(
|
| const HostResolver::RequestInfo& resolve_info) {
|
| + CHECK(!canceled_);
|
| int rv = resolver_.Resolve(resolve_info, &addresses_, &callback_);
|
| if (rv != ERR_IO_PENDING)
|
| rv = OnIOCompleteInternal(rv, true /* synchronous */);
|
| @@ -68,14 +73,30 @@ int TCPClientSocketPool::ConnectingSocket::OnIOCompleteInternal(
|
| int result, bool synchronous) {
|
| CHECK(result != ERR_IO_PENDING);
|
|
|
| + if (canceled_) {
|
| + // We got canceled, so bail out.
|
| + delete this;
|
| + return result;
|
| + }
|
| +
|
| GroupMap::iterator group_it = pool_->group_map_.find(group_name_);
|
| - CHECK(group_it != pool_->group_map_.end());
|
| + if (group_it == pool_->group_map_.end()) {
|
| + // The request corresponding to this ConnectingSocket has been canceled.
|
| + // Stop bothering with it.
|
| + delete this;
|
| + return result;
|
| + }
|
|
|
| Group& group = group_it->second;
|
|
|
| RequestMap* request_map = &group.connecting_requests;
|
| RequestMap::iterator it = request_map->find(handle_);
|
| - CHECK(it != request_map->end());
|
| + if (it == request_map->end()) {
|
| + // The request corresponding to this ConnectingSocket has been canceled.
|
| + // Stop bothering with it.
|
| + delete this;
|
| + return result;
|
| + }
|
|
|
| if (result == OK && it->second.load_state == LOAD_STATE_RESOLVING_HOST) {
|
| it->second.load_state = LOAD_STATE_CONNECTING;
|
| @@ -87,7 +108,6 @@ int TCPClientSocketPool::ConnectingSocket::OnIOCompleteInternal(
|
| }
|
|
|
| if (result == OK) {
|
| - CHECK(it->second.load_state == LOAD_STATE_CONNECTING);
|
| CHECK(connect_start_time_ != base::Time());
|
| base::TimeDelta connect_duration =
|
| base::Time::Now() - connect_start_time_;
|
| @@ -121,10 +141,17 @@ int TCPClientSocketPool::ConnectingSocket::OnIOCompleteInternal(
|
|
|
| if (!synchronous)
|
| request.callback->Run(result);
|
| - pool_->RemoveConnectingSocket(handle_); // will delete |this|.
|
| + delete this;
|
| return result;
|
| }
|
|
|
| +void TCPClientSocketPool::ConnectingSocket::Cancel() {
|
| + CHECK(!canceled_);
|
| + CHECK(ContainsKey(pool_->connecting_socket_map_, handle_));
|
| + pool_->connecting_socket_map_.erase(handle_);
|
| + canceled_ = true;
|
| +}
|
| +
|
| TCPClientSocketPool::TCPClientSocketPool(
|
| int max_sockets_per_group,
|
| HostResolver* host_resolver,
|
| @@ -141,7 +168,6 @@ TCPClientSocketPool::~TCPClientSocketPool() {
|
| // to the manager being destroyed.
|
| CloseIdleSockets();
|
| DCHECK(group_map_.empty());
|
| - DCHECK(connecting_socket_map_.empty());
|
| }
|
|
|
| // InsertRequestIntoQueue inserts the request into the queue based on
|
| @@ -193,16 +219,20 @@ int TCPClientSocketPool::RequestSocket(
|
|
|
| // We couldn't find a socket to reuse, so allocate and connect a new one.
|
|
|
| + // First, we need to make sure we aren't already servicing a request for this
|
| + // handle (which could happen if we requested, canceled, and then requested
|
| + // with the same handle).
|
| + if (ContainsKey(connecting_socket_map_, handle))
|
| + connecting_socket_map_[handle]->Cancel();
|
| +
|
| CHECK(callback);
|
| Request r(handle, callback, priority, resolve_info,
|
| LOAD_STATE_RESOLVING_HOST);
|
| group_map_[group_name].connecting_requests[handle] = r;
|
|
|
| - CHECK(!ContainsKey(connecting_socket_map_, handle));
|
| -
|
| + // connecting_socket will delete itself.
|
| ConnectingSocket* connecting_socket =
|
| new ConnectingSocket(group_name, handle, client_socket_factory_, this);
|
| - connecting_socket_map_[handle] = connecting_socket;
|
| int rv = connecting_socket->Connect(resolve_info);
|
| return rv;
|
| }
|
| @@ -227,8 +257,6 @@ void TCPClientSocketPool::CancelRequest(const std::string& group_name,
|
|
|
| RequestMap::iterator map_it = group.connecting_requests.find(handle);
|
| if (map_it != group.connecting_requests.end()) {
|
| - RemoveConnectingSocket(handle);
|
| -
|
| group.connecting_requests.erase(map_it);
|
| group.active_socket_count--;
|
|
|
| @@ -391,12 +419,4 @@ void TCPClientSocketPool::DoReleaseSocket(const std::string& group_name,
|
| }
|
| }
|
|
|
| -void TCPClientSocketPool::RemoveConnectingSocket(
|
| - const ClientSocketHandle* handle) {
|
| - ConnectingSocketMap::iterator it = connecting_socket_map_.find(handle);
|
| - CHECK(it != connecting_socket_map_.end());
|
| - delete it->second;
|
| - connecting_socket_map_.erase(it);
|
| -}
|
| -
|
| } // namespace net
|
|
|