| Index: net/socket/client_socket_pool_base.cc
|
| diff --git a/net/socket/client_socket_pool_base.cc b/net/socket/client_socket_pool_base.cc
|
| index b008c54378c3d8f2b1db98bdc602439c92fd1483..820e9e2eea8f4047e3a95c9e1820f055e558fd09 100644
|
| --- a/net/socket/client_socket_pool_base.cc
|
| +++ b/net/socket/client_socket_pool_base.cc
|
| @@ -187,23 +187,6 @@ int ClientSocketPoolBaseHelper::RequestSocketInternal(
|
| CHECK(handle);
|
| Group& group = group_map_[group_name];
|
|
|
| - // Can we make another active socket now?
|
| - if (ReachedMaxSocketsLimit() ||
|
| - !group.HasAvailableSocketSlot(max_sockets_per_group_)) {
|
| - if (ReachedMaxSocketsLimit()) {
|
| - // We could check if we really have a stalled group here, but it requires
|
| - // a scan of all groups, so just flip a flag here, and do the check later.
|
| - may_have_stalled_group_ = true;
|
| -
|
| - request->net_log().AddEvent(NetLog::TYPE_SOCKET_POOL_STALLED_MAX_SOCKETS,
|
| - NULL);
|
| - } else {
|
| - request->net_log().AddEvent(
|
| - NetLog::TYPE_SOCKET_POOL_STALLED_MAX_SOCKETS_PER_GROUP, NULL);
|
| - }
|
| - return ERR_IO_PENDING;
|
| - }
|
| -
|
| // Try to reuse a socket.
|
| while (!group.idle_sockets.empty()) {
|
| IdleSocket idle_socket = group.idle_sockets.back();
|
| @@ -221,6 +204,26 @@ int ClientSocketPoolBaseHelper::RequestSocketInternal(
|
| delete idle_socket.socket;
|
| }
|
|
|
| + // Can we make another active socket now?
|
| + if (!group.HasAvailableSocketSlot(max_sockets_per_group_)) {
|
| + request->net_log().AddEvent(
|
| + NetLog::TYPE_SOCKET_POOL_STALLED_MAX_SOCKETS_PER_GROUP, NULL);
|
| + return ERR_IO_PENDING;
|
| + }
|
| +
|
| + if (ReachedMaxSocketsLimit()) {
|
| + if (idle_socket_count() > 0) {
|
| + CloseOneIdleSocket();
|
| + } else {
|
| + // We could check if we really have a stalled group here, but it requires
|
| + // a scan of all groups, so just flip a flag here, and do the check later.
|
| + may_have_stalled_group_ = true;
|
| + request->net_log().AddEvent(
|
| + NetLog::TYPE_SOCKET_POOL_STALLED_MAX_SOCKETS, NULL);
|
| + return ERR_IO_PENDING;
|
| + }
|
| + }
|
| +
|
| // See if we already have enough connect jobs or sockets that will be released
|
| // soon.
|
| if (group.HasReleasingSockets()) {
|
| @@ -502,10 +505,14 @@ void ClientSocketPoolBaseHelper::DoReleaseSocket(const std::string& group_name,
|
| int stalled_group_count = FindTopStalledGroup(&top_group, &top_group_name);
|
| if (stalled_group_count >= 1) {
|
| if (ReachedMaxSocketsLimit()) {
|
| - // We can't activate more sockets since we're already at our global
|
| - // limit.
|
| - may_have_stalled_group_ = true;
|
| - return;
|
| + if (idle_socket_count() > 0) {
|
| + CloseOneIdleSocket();
|
| + } else {
|
| + // We can't activate more sockets since we're already at our global
|
| + // limit.
|
| + may_have_stalled_group_ = true;
|
| + return;
|
| + }
|
| }
|
|
|
| ProcessPendingRequest(top_group_name, top_group);
|
| @@ -636,8 +643,10 @@ void ClientSocketPoolBaseHelper::OnAvailableSocketSlot(
|
| (stalled_group_count == 1 && top_group->num_releasing_sockets == 0)) {
|
| may_have_stalled_group_ = false;
|
| }
|
| - if (stalled_group_count >= 1)
|
| + if (stalled_group_count >= 1) {
|
| + CHECK_GE(1, idle_socket_count());
|
| ProcessPendingRequest(top_group_name, top_group);
|
| + }
|
| } else if (!group->pending_requests.empty()) {
|
| ProcessPendingRequest(group_name, group);
|
| // |group| may no longer be valid after this point. Be careful not to
|
| @@ -726,7 +735,8 @@ void ClientSocketPoolBaseHelper::CancelAllConnectJobs() {
|
|
|
| bool ClientSocketPoolBaseHelper::ReachedMaxSocketsLimit() const {
|
| // Each connecting socket will eventually connect and be handed out.
|
| - int total = handed_out_socket_count_ + connecting_socket_count_;
|
| + int total = handed_out_socket_count_ + connecting_socket_count_ +
|
| + idle_socket_count();
|
| DCHECK_LE(total, max_sockets_);
|
| if (total < max_sockets_)
|
| return false;
|
| @@ -734,6 +744,27 @@ bool ClientSocketPoolBaseHelper::ReachedMaxSocketsLimit() const {
|
| return true;
|
| }
|
|
|
| +void ClientSocketPoolBaseHelper::CloseOneIdleSocket() {
|
| + CHECK_GT(idle_socket_count(), 0);
|
| +
|
| + for (GroupMap::iterator i = group_map_.begin(); i != group_map_.end(); ++i) {
|
| + Group& group = i->second;
|
| +
|
| + if (!group.idle_sockets.empty()) {
|
| + std::deque<IdleSocket>::iterator j = group.idle_sockets.begin();
|
| + delete j->socket;
|
| + group.idle_sockets.erase(j);
|
| + DecrementIdleCount();
|
| + if (group.IsEmpty())
|
| + group_map_.erase(i);
|
| +
|
| + return;
|
| + }
|
| + }
|
| +
|
| + LOG(DFATAL) << "No idle socket found to close!.";
|
| +}
|
| +
|
| } // namespace internal
|
|
|
| } // namespace net
|
|
|