Chromium Code Reviews

Side by Side Diff: net/socket/client_socket_pool_base.cc

Issue 5549001: Fix preconnect crash when we hit max socket limit. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Add TODO, fix lint error. Created 10 years ago
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff | | Annotate | Revision Log
« no previous file with comments | « net/socket/client_socket_pool_base.h ('k') | net/socket/client_socket_pool_base_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "net/socket/client_socket_pool_base.h" 5 #include "net/socket/client_socket_pool_base.h"
6 6
7 #include "base/compiler_specific.h" 7 #include "base/compiler_specific.h"
8 #include "base/format_macros.h" 8 #include "base/format_macros.h"
9 #include "base/message_loop.h" 9 #include "base/message_loop.h"
10 #include "base/metrics/stats_counters.h" 10 #include "base/metrics/stats_counters.h"
(...skipping 232 matching lines...)
243 243
244 Group* group = GetOrCreateGroup(group_name); 244 Group* group = GetOrCreateGroup(group_name);
245 245
246 // RequestSocketsInternal() may delete the group. 246 // RequestSocketsInternal() may delete the group.
247 bool deleted_group = false; 247 bool deleted_group = false;
248 248
249 for (int num_iterations_left = num_sockets; 249 for (int num_iterations_left = num_sockets;
250 group->NumActiveSocketSlots() < num_sockets && 250 group->NumActiveSocketSlots() < num_sockets &&
251 num_iterations_left > 0 ; num_iterations_left--) { 251 num_iterations_left > 0 ; num_iterations_left--) {
252 int rv = RequestSocketInternal(group_name, &request); 252 int rv = RequestSocketInternal(group_name, &request);
253 // TODO(willchan): Possibly check for ERR_PRECONNECT_MAX_SOCKET_LIMIT so we
254 // can log it into the NetLog.
253 if (rv < 0 && rv != ERR_IO_PENDING) { 255 if (rv < 0 && rv != ERR_IO_PENDING) {
254 // We're encountering a synchronous error. Give up. 256 // We're encountering a synchronous error. Give up.
255 if (!ContainsKey(group_map_, group_name)) 257 if (!ContainsKey(group_map_, group_name))
256 deleted_group = true; 258 deleted_group = true;
257 break; 259 break;
258 } 260 }
259 if (!ContainsKey(group_map_, group_name)) { 261 if (!ContainsKey(group_map_, group_name)) {
260 // Unexpected. The group should only be getting deleted on synchronous 262 // Unexpected. The group should only be getting deleted on synchronous
261 // error. 263 // error.
262 NOTREACHED(); 264 NOTREACHED();
(...skipping 28 matching lines...)
291 293
292 // Can we make another active socket now? 294 // Can we make another active socket now?
293 if (!group->HasAvailableSocketSlot(max_sockets_per_group_)) { 295 if (!group->HasAvailableSocketSlot(max_sockets_per_group_)) {
294 request->net_log().AddEvent( 296 request->net_log().AddEvent(
295 NetLog::TYPE_SOCKET_POOL_STALLED_MAX_SOCKETS_PER_GROUP, NULL); 297 NetLog::TYPE_SOCKET_POOL_STALLED_MAX_SOCKETS_PER_GROUP, NULL);
296 return ERR_IO_PENDING; 298 return ERR_IO_PENDING;
297 } 299 }
298 300
299 if (ReachedMaxSocketsLimit()) { 301 if (ReachedMaxSocketsLimit()) {
300 if (idle_socket_count() > 0) { 302 if (idle_socket_count() > 0) {
301 CloseOneIdleSocket(); 303 bool closed = CloseOneIdleSocketExceptInGroup(group);
304 if (preconnecting && !closed)
305 return ERR_PRECONNECT_MAX_SOCKET_LIMIT;
302 } else { 306 } else {
303 // We could check if we really have a stalled group here, but it requires 307 // We could check if we really have a stalled group here, but it requires
304 // a scan of all groups, so just flip a flag here, and do the check later. 308 // a scan of all groups, so just flip a flag here, and do the check later.
305 request->net_log().AddEvent( 309 request->net_log().AddEvent(
306 NetLog::TYPE_SOCKET_POOL_STALLED_MAX_SOCKETS, NULL); 310 NetLog::TYPE_SOCKET_POOL_STALLED_MAX_SOCKETS, NULL);
307 return ERR_IO_PENDING; 311 return ERR_IO_PENDING;
308 } 312 }
309 } 313 }
310 314
311 // We couldn't find a socket to reuse, so allocate and connect a new one. 315 // We couldn't find a socket to reuse, so allocate and connect a new one.
(...skipping 621 matching lines...)
933 // Each connecting socket will eventually connect and be handed out. 937 // Each connecting socket will eventually connect and be handed out.
934 int total = handed_out_socket_count_ + connecting_socket_count_ + 938 int total = handed_out_socket_count_ + connecting_socket_count_ +
935 idle_socket_count(); 939 idle_socket_count();
936 DCHECK_LE(total, max_sockets_); 940 DCHECK_LE(total, max_sockets_);
937 if (total < max_sockets_) 941 if (total < max_sockets_)
938 return false; 942 return false;
939 return true; 943 return true;
940 } 944 }
941 945
942 void ClientSocketPoolBaseHelper::CloseOneIdleSocket() { 946 void ClientSocketPoolBaseHelper::CloseOneIdleSocket() {
947 CloseOneIdleSocketExceptInGroup(NULL);
948 }
949
950 bool ClientSocketPoolBaseHelper::CloseOneIdleSocketExceptInGroup(
951 const Group* exception_group) {
943 CHECK_GT(idle_socket_count(), 0); 952 CHECK_GT(idle_socket_count(), 0);
944 953
945 for (GroupMap::iterator i = group_map_.begin(); i != group_map_.end(); ++i) { 954 for (GroupMap::iterator i = group_map_.begin(); i != group_map_.end(); ++i) {
946 Group* group = i->second; 955 Group* group = i->second;
956 if (exception_group == group)
957 continue;
947 std::list<IdleSocket>* idle_sockets = group->mutable_idle_sockets(); 958 std::list<IdleSocket>* idle_sockets = group->mutable_idle_sockets();
948 959
949 if (!idle_sockets->empty()) { 960 if (!idle_sockets->empty()) {
950 delete idle_sockets->front().socket; 961 delete idle_sockets->front().socket;
951 idle_sockets->pop_front(); 962 idle_sockets->pop_front();
952 DecrementIdleCount(); 963 DecrementIdleCount();
953 if (group->IsEmpty()) 964 if (group->IsEmpty())
954 RemoveGroup(i); 965 RemoveGroup(i);
955 966
956 return; 967 return true;
957 } 968 }
958 } 969 }
959 970
960 LOG(DFATAL) << "No idle socket found to close!."; 971 if (!exception_group)
972 LOG(DFATAL) << "No idle socket found to close!.";
973
974 return false;
961 } 975 }
962 976
963 void ClientSocketPoolBaseHelper::InvokeUserCallbackLater( 977 void ClientSocketPoolBaseHelper::InvokeUserCallbackLater(
964 ClientSocketHandle* handle, CompletionCallback* callback, int rv) { 978 ClientSocketHandle* handle, CompletionCallback* callback, int rv) {
965 CHECK(!ContainsKey(pending_callback_map_, handle)); 979 CHECK(!ContainsKey(pending_callback_map_, handle));
966 pending_callback_map_[handle] = CallbackResultPair(callback, rv); 980 pending_callback_map_[handle] = CallbackResultPair(callback, rv);
967 MessageLoop::current()->PostTask( 981 MessageLoop::current()->PostTask(
968 FROM_HERE, 982 FROM_HERE,
969 method_factory_.NewRunnableMethod( 983 method_factory_.NewRunnableMethod(
970 &ClientSocketPoolBaseHelper::InvokeUserCallback, 984 &ClientSocketPoolBaseHelper::InvokeUserCallback,
(...skipping 88 matching lines...)
1059 // Delete active jobs. 1073 // Delete active jobs.
1060 STLDeleteElements(&jobs_); 1074 STLDeleteElements(&jobs_);
1061 1075
1062 // Cancel pending backup job. 1076 // Cancel pending backup job.
1063 method_factory_.RevokeAll(); 1077 method_factory_.RevokeAll();
1064 } 1078 }
1065 1079
1066 } // namespace internal 1080 } // namespace internal
1067 1081
1068 } // namespace net 1082 } // namespace net
OLDNEW
« no previous file with comments | « net/socket/client_socket_pool_base.h ('k') | net/socket/client_socket_pool_base_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine