summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwillchan@chromium.org <willchan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-03-02 18:31:04 +0000
committerwillchan@chromium.org <willchan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-03-02 18:31:04 +0000
commit4f1e498f30a2906b1a546d8dec3e2171eaff4e67 (patch)
tree9d5b7625fa99cc44142e092108a86f2080230867
parent37199a82379c63b9daad59ba5bfb9ab99f23f7b9 (diff)
downloadchromium_src-4f1e498f30a2906b1a546d8dec3e2171eaff4e67.zip
chromium_src-4f1e498f30a2906b1a546d8dec3e2171eaff4e67.tar.gz
chromium_src-4f1e498f30a2906b1a546d8dec3e2171eaff4e67.tar.bz2
Fix infinite loop in ClientSocketPoolBase::DoReleaseSocket.
BUG=36871 Review URL: http://codereview.chromium.org/660353 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@40395 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--net/socket/client_socket_pool_base.cc5
-rw-r--r--net/socket/client_socket_pool_base_unittest.cc53
2 files changed, 55 insertions, 3 deletions
diff --git a/net/socket/client_socket_pool_base.cc b/net/socket/client_socket_pool_base.cc
index 75081a2..ed188fd 100644
--- a/net/socket/client_socket_pool_base.cc
+++ b/net/socket/client_socket_pool_base.cc
@@ -413,14 +413,13 @@ void ClientSocketPoolBaseHelper::DoReleaseSocket(const std::string& group_name,
delete socket;
}
- const bool more_releasing_sockets = group.num_releasing_sockets > 0;
-
OnAvailableSocketSlot(group_name, &group);
// If there are no more releasing sockets, then we might have to process
// multiple available socket slots, since we stalled their processing until
// all sockets have been released.
- if (more_releasing_sockets)
+ i = group_map_.find(group_name);
+ if (i == group_map_.end() || i->second.num_releasing_sockets > 0)
return;
while (true) {
diff --git a/net/socket/client_socket_pool_base_unittest.cc b/net/socket/client_socket_pool_base_unittest.cc
index ea32d1b..9fe7684 100644
--- a/net/socket/client_socket_pool_base_unittest.cc
+++ b/net/socket/client_socket_pool_base_unittest.cc
@@ -1443,6 +1443,59 @@ TEST_F(ClientSocketPoolBaseTest,
EXPECT_EQ(kIndexOutOfBounds, GetOrderOfRequest(5));
}
+class TestReleasingSocketRequest : public CallbackRunner< Tuple1<int> > {
+ public:
+ explicit TestReleasingSocketRequest(TestClientSocketPool* pool)
+ : pool_(pool) {}
+
+ ClientSocketHandle* handle() { return &handle_; }
+
+ int WaitForResult() {
+ return callback_.WaitForResult();
+ }
+
+ virtual void RunWithParams(const Tuple1<int>& params) {
+ callback_.RunWithParams(params);
+ handle_.Reset();
+ EXPECT_EQ(ERR_IO_PENDING,
+ InitHandle(&handle2_, "a", kDefaultPriority,
+ &callback2_, pool_, NULL));
+ }
+
+ private:
+ TestClientSocketPool* const pool_;
+ ClientSocketHandle handle_;
+ ClientSocketHandle handle2_;
+ TestCompletionCallback callback_;
+ TestCompletionCallback callback2_;
+};
+
+// This test covers the case where, within the same DoReleaseSocket() callback,
+// we release the just acquired socket and start up a new request. See bug
+// 36871 for details.
+TEST_F(ClientSocketPoolBaseTest, ReleasedSocketReleasesToo) {
+ CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup);
+
+ connect_job_factory_->set_job_type(TestConnectJob::kMockJob);
+
+ // Complete one request and release the socket.
+ ClientSocketHandle handle;
+ TestCompletionCallback callback;
+ EXPECT_EQ(OK, InitHandle(
+ &handle, "a", kDefaultPriority, &callback, pool_.get(), NULL));
+ handle.Reset();
+
+ // Before the DoReleaseSocket() task has run, start up a
+ // TestReleasingSocketRequest. This one will be ERR_IO_PENDING since
+ // num_releasing_sockets > 0 and there was no idle socket to use yet.
+ TestReleasingSocketRequest request(pool_.get());
+ EXPECT_EQ(ERR_IO_PENDING,
+ InitHandle(request.handle(), "a", kDefaultPriority, &request,
+ pool_.get(), NULL));
+
+ EXPECT_EQ(OK, request.WaitForResult());
+}
+
} // namespace
} // namespace net