Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(57)

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: Created 10 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | 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 228 matching lines...) Expand 10 before | Expand all | Expand 10 after
239 request.net_log().BeginEvent( 239 request.net_log().BeginEvent(
240 NetLog::TYPE_SOCKET_POOL_CONNECTING_N_SOCKETS, 240 NetLog::TYPE_SOCKET_POOL_CONNECTING_N_SOCKETS,
241 make_scoped_refptr(new NetLogIntegerParameter( 241 make_scoped_refptr(new NetLogIntegerParameter(
242 "num_sockets", num_sockets))); 242 "num_sockets", num_sockets)));
243 243
244 Group* group = GetOrCreateGroup(group_name); 244 Group* group = GetOrCreateGroup(group_name);
245 245
246 for (int num_iterations_left = num_sockets; 246 for (int num_iterations_left = num_sockets;
247 group->NumActiveSocketSlots() < num_sockets && 247 group->NumActiveSocketSlots() < num_sockets &&
248 num_iterations_left > 0 ; num_iterations_left--) { 248 num_iterations_left > 0 ; num_iterations_left--) {
249 int rv = RequestSocketInternal(group_name, &request); 249 int rv = RequestSocketInternal(group_name, &request);
willchan no longer on Chromium 2010/12/02 01:58:07 Should I special case ERR_PRECONNECT_MAX_SOCKET_LI
Mike Belshe 2010/12/02 02:46:48 It's up to you. Maybe add a TODO
250 if (rv < 0 && rv != ERR_IO_PENDING) { 250 if (rv < 0 && rv != ERR_IO_PENDING) {
251 // We're encountering a synchronous error. Give up. 251 // We're encountering a synchronous error. Give up.
252 break; 252 break;
253 } 253 }
254 } 254 }
255 255
256 if (group->IsEmpty()) 256 if (group->IsEmpty())
257 RemoveGroup(group_name); 257 RemoveGroup(group_name);
258 258
259 request.net_log().EndEvent( 259 request.net_log().EndEvent(
(...skipping 19 matching lines...) Expand all
279 279
280 // Can we make another active socket now? 280 // Can we make another active socket now?
281 if (!group->HasAvailableSocketSlot(max_sockets_per_group_)) { 281 if (!group->HasAvailableSocketSlot(max_sockets_per_group_)) {
282 request->net_log().AddEvent( 282 request->net_log().AddEvent(
283 NetLog::TYPE_SOCKET_POOL_STALLED_MAX_SOCKETS_PER_GROUP, NULL); 283 NetLog::TYPE_SOCKET_POOL_STALLED_MAX_SOCKETS_PER_GROUP, NULL);
284 return ERR_IO_PENDING; 284 return ERR_IO_PENDING;
285 } 285 }
286 286
287 if (ReachedMaxSocketsLimit()) { 287 if (ReachedMaxSocketsLimit()) {
288 if (idle_socket_count() > 0) { 288 if (idle_socket_count() > 0) {
289 CloseOneIdleSocket(); 289 bool closed = CloseOneIdleSocketExceptInGroup(group);
290 if (preconnecting && !closed)
291 return ERR_PRECONNECT_MAX_SOCKET_LIMIT;
290 } else { 292 } else {
291 // We could check if we really have a stalled group here, but it requires 293 // We could check if we really have a stalled group here, but it requires
292 // a scan of all groups, so just flip a flag here, and do the check later. 294 // a scan of all groups, so just flip a flag here, and do the check later.
293 request->net_log().AddEvent( 295 request->net_log().AddEvent(
294 NetLog::TYPE_SOCKET_POOL_STALLED_MAX_SOCKETS, NULL); 296 NetLog::TYPE_SOCKET_POOL_STALLED_MAX_SOCKETS, NULL);
295 return ERR_IO_PENDING; 297 return ERR_IO_PENDING;
296 } 298 }
297 } 299 }
298 300
299 // We couldn't find a socket to reuse, so allocate and connect a new one. 301 // We couldn't find a socket to reuse, so allocate and connect a new one.
(...skipping 621 matching lines...) Expand 10 before | Expand all | Expand 10 after
921 // Each connecting socket will eventually connect and be handed out. 923 // Each connecting socket will eventually connect and be handed out.
922 int total = handed_out_socket_count_ + connecting_socket_count_ + 924 int total = handed_out_socket_count_ + connecting_socket_count_ +
923 idle_socket_count(); 925 idle_socket_count();
924 DCHECK_LE(total, max_sockets_); 926 DCHECK_LE(total, max_sockets_);
925 if (total < max_sockets_) 927 if (total < max_sockets_)
926 return false; 928 return false;
927 return true; 929 return true;
928 } 930 }
929 931
930 void ClientSocketPoolBaseHelper::CloseOneIdleSocket() { 932 void ClientSocketPoolBaseHelper::CloseOneIdleSocket() {
933 CloseOneIdleSocketExceptInGroup(NULL);
934 }
935
936 bool ClientSocketPoolBaseHelper::CloseOneIdleSocketExceptInGroup(
937 const Group* exception_group) {
931 CHECK_GT(idle_socket_count(), 0); 938 CHECK_GT(idle_socket_count(), 0);
932 939
933 for (GroupMap::iterator i = group_map_.begin(); i != group_map_.end(); ++i) { 940 for (GroupMap::iterator i = group_map_.begin(); i != group_map_.end(); ++i) {
934 Group* group = i->second; 941 Group* group = i->second;
942 if (exception_group == group)
943 continue;
935 std::list<IdleSocket>* idle_sockets = group->mutable_idle_sockets(); 944 std::list<IdleSocket>* idle_sockets = group->mutable_idle_sockets();
936 945
937 if (!idle_sockets->empty()) { 946 if (!idle_sockets->empty()) {
938 delete idle_sockets->front().socket; 947 delete idle_sockets->front().socket;
939 idle_sockets->pop_front(); 948 idle_sockets->pop_front();
940 DecrementIdleCount(); 949 DecrementIdleCount();
941 if (group->IsEmpty()) 950 if (group->IsEmpty())
942 RemoveGroup(i); 951 RemoveGroup(i);
943 952
944 return; 953 return true;
945 } 954 }
946 } 955 }
947 956
948 LOG(DFATAL) << "No idle socket found to close!."; 957 if (!exception_group)
958 LOG(DFATAL) << "No idle socket found to close!.";
959
960 return false;
949 } 961 }
950 962
951 void ClientSocketPoolBaseHelper::InvokeUserCallbackLater( 963 void ClientSocketPoolBaseHelper::InvokeUserCallbackLater(
952 ClientSocketHandle* handle, CompletionCallback* callback, int rv) { 964 ClientSocketHandle* handle, CompletionCallback* callback, int rv) {
953 CHECK(!ContainsKey(pending_callback_map_, handle)); 965 CHECK(!ContainsKey(pending_callback_map_, handle));
954 pending_callback_map_[handle] = CallbackResultPair(callback, rv); 966 pending_callback_map_[handle] = CallbackResultPair(callback, rv);
955 MessageLoop::current()->PostTask( 967 MessageLoop::current()->PostTask(
956 FROM_HERE, 968 FROM_HERE,
957 method_factory_.NewRunnableMethod( 969 method_factory_.NewRunnableMethod(
958 &ClientSocketPoolBaseHelper::InvokeUserCallback, 970 &ClientSocketPoolBaseHelper::InvokeUserCallback,
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
1047 // Delete active jobs. 1059 // Delete active jobs.
1048 STLDeleteElements(&jobs_); 1060 STLDeleteElements(&jobs_);
1049 1061
1050 // Cancel pending backup job. 1062 // Cancel pending backup job.
1051 method_factory_.RevokeAll(); 1063 method_factory_.RevokeAll();
1052 } 1064 }
1053 1065
1054 } // namespace internal 1066 } // namespace internal
1055 1067
1056 } // namespace net 1068 } // 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
This is Rietveld 408576698