Fix idle socket cleanup code path.

This reverses the order that sockets removed from the idle list and deleted.
It also detects and handles recursive calls to CleanupIdleSockets.

BUG=49387
TEST=none

Review URL: http://codereview.chromium.org/2856049

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@53374 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/net/socket/client_socket_pool_base.cc b/net/socket/client_socket_pool_base.cc
index e4a611b3..3ab6334 100644
--- a/net/socket/client_socket_pool_base.cc
+++ b/net/socket/client_socket_pool_base.cc
@@ -139,7 +139,8 @@
       connect_job_factory_(connect_job_factory),
       backup_jobs_enabled_(false),
       ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)),
-      pool_generation_number_(0) {
+      pool_generation_number_(0),
+      in_destructor_(false) {
   DCHECK_LE(0, max_sockets_per_group);
   DCHECK_LE(max_sockets_per_group, max_sockets);
 
@@ -147,6 +148,7 @@
 }
 
 ClientSocketPoolBaseHelper::~ClientSocketPoolBaseHelper() {
+  in_destructor_ = true;
   CancelAllConnectJobs();
 
   // Clean up any idle sockets.  Assert that we have no remaining active
@@ -455,6 +457,14 @@
   if (idle_socket_count_ == 0)
     return;
 
+  // Deleting an SSL socket may remove the last reference to an
+  // HttpNetworkSession (in an incognito session), triggering the destruction
+  // of pools, potentially causing a recursive call to this function.  Hold a
+  // reference to |this| to prevent that.
+  scoped_refptr<ClientSocketPoolBaseHelper> protect_this;
+  if (!in_destructor_)
+    protect_this = this;
+
   // Current time value. Retrieving it once at the function start rather than
   // inside the inner loop, since it shouldn't change by any meaningful amount.
   base::TimeTicks now = base::TimeTicks::Now();