diff options
author | willchan@chromium.org <willchan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-03-02 18:31:04 +0000 |
---|---|---|
committer | willchan@chromium.org <willchan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-03-02 18:31:04 +0000 |
commit | 4f1e498f30a2906b1a546d8dec3e2171eaff4e67 (patch) | |
tree | 9d5b7625fa99cc44142e092108a86f2080230867 | |
parent | 37199a82379c63b9daad59ba5bfb9ab99f23f7b9 (diff) | |
download | chromium_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.cc | 5 | ||||
-rw-r--r-- | net/socket/client_socket_pool_base_unittest.cc | 53 |
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 |