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

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

Issue 1992010: Revert 46757 - Fix IO thread hang on releasing a socket.... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 10 years, 7 months 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/stats_counters.h" 10 #include "base/stats_counters.h"
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
110 ClientSocketPoolBaseHelper::ClientSocketPoolBaseHelper( 110 ClientSocketPoolBaseHelper::ClientSocketPoolBaseHelper(
111 int max_sockets, 111 int max_sockets,
112 int max_sockets_per_group, 112 int max_sockets_per_group,
113 base::TimeDelta unused_idle_socket_timeout, 113 base::TimeDelta unused_idle_socket_timeout,
114 base::TimeDelta used_idle_socket_timeout, 114 base::TimeDelta used_idle_socket_timeout,
115 ConnectJobFactory* connect_job_factory, 115 ConnectJobFactory* connect_job_factory,
116 NetworkChangeNotifier* network_change_notifier) 116 NetworkChangeNotifier* network_change_notifier)
117 : idle_socket_count_(0), 117 : idle_socket_count_(0),
118 connecting_socket_count_(0), 118 connecting_socket_count_(0),
119 handed_out_socket_count_(0), 119 handed_out_socket_count_(0),
120 num_releasing_sockets_(0),
121 max_sockets_(max_sockets), 120 max_sockets_(max_sockets),
122 max_sockets_per_group_(max_sockets_per_group), 121 max_sockets_per_group_(max_sockets_per_group),
123 unused_idle_socket_timeout_(unused_idle_socket_timeout), 122 unused_idle_socket_timeout_(unused_idle_socket_timeout),
124 used_idle_socket_timeout_(used_idle_socket_timeout), 123 used_idle_socket_timeout_(used_idle_socket_timeout),
125 may_have_stalled_group_(false), 124 may_have_stalled_group_(false),
126 connect_job_factory_(connect_job_factory), 125 connect_job_factory_(connect_job_factory),
127 network_change_notifier_(network_change_notifier), 126 network_change_notifier_(network_change_notifier),
128 backup_jobs_enabled_(false), 127 backup_jobs_enabled_(false),
129 ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) { 128 ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) {
130 DCHECK_LE(0, max_sockets_per_group); 129 DCHECK_LE(0, max_sockets_per_group);
(...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after
352 } 351 }
353 return; 352 return;
354 } 353 }
355 } 354 }
356 } 355 }
357 356
358 void ClientSocketPoolBaseHelper::ReleaseSocket(const std::string& group_name, 357 void ClientSocketPoolBaseHelper::ReleaseSocket(const std::string& group_name,
359 ClientSocket* socket) { 358 ClientSocket* socket) {
360 Group& group = group_map_[group_name]; 359 Group& group = group_map_[group_name];
361 group.num_releasing_sockets++; 360 group.num_releasing_sockets++;
362 num_releasing_sockets_++;
363 DCHECK_LE(group.num_releasing_sockets, group.active_socket_count); 361 DCHECK_LE(group.num_releasing_sockets, group.active_socket_count);
364 // Run this asynchronously to allow the caller to finish before we let 362 // Run this asynchronously to allow the caller to finish before we let
365 // another to begin doing work. This also avoids nasty recursion issues. 363 // another to begin doing work. This also avoids nasty recursion issues.
366 // NOTE: We cannot refer to the handle argument after this method returns. 364 // NOTE: We cannot refer to the handle argument after this method returns.
367 MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod( 365 MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod(
368 this, &ClientSocketPoolBaseHelper::DoReleaseSocket, group_name, socket)); 366 this, &ClientSocketPoolBaseHelper::DoReleaseSocket, group_name, socket));
369 } 367 }
370 368
371 void ClientSocketPoolBaseHelper::CloseIdleSockets() { 369 void ClientSocketPoolBaseHelper::CloseIdleSockets() {
372 CleanupIdleSockets(true); 370 CleanupIdleSockets(true);
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
477 475
478 group.num_releasing_sockets--; 476 group.num_releasing_sockets--;
479 DCHECK_GE(group.num_releasing_sockets, 0); 477 DCHECK_GE(group.num_releasing_sockets, 0);
480 478
481 CHECK_GT(handed_out_socket_count_, 0); 479 CHECK_GT(handed_out_socket_count_, 0);
482 handed_out_socket_count_--; 480 handed_out_socket_count_--;
483 481
484 CHECK_GT(group.active_socket_count, 0); 482 CHECK_GT(group.active_socket_count, 0);
485 group.active_socket_count--; 483 group.active_socket_count--;
486 484
487 CHECK_GT(num_releasing_sockets_, 0);
488 num_releasing_sockets_--;
489
490 const bool can_reuse = socket->IsConnectedAndIdle(); 485 const bool can_reuse = socket->IsConnectedAndIdle();
491 if (can_reuse) { 486 if (can_reuse) {
492 AddIdleSocket(socket, true /* used socket */, &group); 487 AddIdleSocket(socket, true /* used socket */, &group);
493 } else { 488 } else {
494 delete socket; 489 delete socket;
495 } 490 }
496 491
492 OnAvailableSocketSlot(group_name, &group);
493
497 // If there are no more releasing sockets, then we might have to process 494 // If there are no more releasing sockets, then we might have to process
498 // multiple available socket slots, since we stalled their processing until 495 // multiple available socket slots, since we stalled their processing until
499 // all sockets have been released. Note that ProcessPendingRequest() will 496 // all sockets have been released.
500 // invoke user callbacks, so |num_releasing_sockets_| may change. 497 i = group_map_.find(group_name);
501 // 498 if (i == group_map_.end() || i->second.num_releasing_sockets > 0)
502 // This code has been known to infinite loop. Set a counter and CHECK to make 499 return;
503 // sure it doesn't get ridiculously high.
504 500
505 int iterations = 0; 501 while (true) {
506 while (num_releasing_sockets_ == 0) { 502 // We can't activate more sockets since we're already at our global limit.
507 CHECK_LT(iterations, 100000) << "Probably stuck in an infinite loop."; 503 if (ReachedMaxSocketsLimit())
508 std::string top_group_name; 504 return;
509 Group* top_group = NULL;
510 int stalled_group_count = FindTopStalledGroup(&top_group, &top_group_name);
511 if (stalled_group_count >= 1) {
512 if (ReachedMaxSocketsLimit()) {
513 // We can't activate more sockets since we're already at our global
514 // limit.
515 may_have_stalled_group_ = true;
516 return;
517 }
518 505
519 ProcessPendingRequest(top_group_name, top_group); 506 // |group| might now be deleted.
520 } else { 507 i = group_map_.find(group_name);
521 may_have_stalled_group_ = false; 508 if (i == group_map_.end())
522 return; 509 return;
523 }
524 510
525 iterations++; 511 group = i->second;
512
513 // If we already have enough ConnectJobs to satisfy the pending requests,
514 // don't bother starting up more.
515 if (group.pending_requests.size() <= group.jobs.size())
516 return;
517
518 if (!group.HasAvailableSocketSlot(max_sockets_per_group_))
519 return;
520
521 OnAvailableSocketSlot(group_name, &group);
526 } 522 }
527 } 523 }
528 524
529 // Search for the highest priority pending request, amongst the groups that 525 // Search for the highest priority pending request, amongst the groups that
530 // are not at the |max_sockets_per_group_| limit. Note: for requests with 526 // are not at the |max_sockets_per_group_| limit. Note: for requests with
531 // the same priority, the winner is based on group hash ordering (and not 527 // the same priority, the winner is based on group hash ordering (and not
532 // insertion order). 528 // insertion order).
533 int ClientSocketPoolBaseHelper::FindTopStalledGroup(Group** group, 529 int ClientSocketPoolBaseHelper::FindTopStalledGroup(Group** group,
534 std::string* group_name) { 530 std::string* group_name) {
535 Group* top_group = NULL; 531 Group* top_group = NULL;
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
637 OnAvailableSocketSlot(group_name, &group); 633 OnAvailableSocketSlot(group_name, &group);
638 } 634 }
639 } 635 }
640 636
641 void ClientSocketPoolBaseHelper::OnAvailableSocketSlot( 637 void ClientSocketPoolBaseHelper::OnAvailableSocketSlot(
642 const std::string& group_name, Group* group) { 638 const std::string& group_name, Group* group) {
643 if (may_have_stalled_group_) { 639 if (may_have_stalled_group_) {
644 std::string top_group_name; 640 std::string top_group_name;
645 Group* top_group = NULL; 641 Group* top_group = NULL;
646 int stalled_group_count = FindTopStalledGroup(&top_group, &top_group_name); 642 int stalled_group_count = FindTopStalledGroup(&top_group, &top_group_name);
647 if (stalled_group_count <= 1 && top_group->num_releasing_sockets == 0) 643 if (stalled_group_count <= 1)
648 may_have_stalled_group_ = false; 644 may_have_stalled_group_ = false;
649 if (stalled_group_count >= 1) 645 if (stalled_group_count >= 1)
650 ProcessPendingRequest(top_group_name, top_group); 646 ProcessPendingRequest(top_group_name, top_group);
651 } else if (!group->pending_requests.empty()) { 647 } else if (!group->pending_requests.empty()) {
652 ProcessPendingRequest(group_name, group); 648 ProcessPendingRequest(group_name, group);
653 // |group| may no longer be valid after this point. Be careful not to 649 // |group| may no longer be valid after this point. Be careful not to
654 // access it again. 650 // access it again.
655 } else if (group->IsEmpty()) { 651 } else if (group->IsEmpty()) {
656 // Delete |group| if no longer needed. |group| will no longer be valid. 652 // Delete |group| if no longer needed. |group| will no longer be valid.
657 group_map_.erase(group_name); 653 group_map_.erase(group_name);
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
740 DCHECK_LE(total, max_sockets_); 736 DCHECK_LE(total, max_sockets_);
741 if (total < max_sockets_) 737 if (total < max_sockets_)
742 return false; 738 return false;
743 LOG(WARNING) << "ReachedMaxSocketsLimit: " << total << "/" << max_sockets_; 739 LOG(WARNING) << "ReachedMaxSocketsLimit: " << total << "/" << max_sockets_;
744 return true; 740 return true;
745 } 741 }
746 742
747 } // namespace internal 743 } // namespace internal
748 744
749 } // namespace net 745 } // 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