summaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authormbelshe@chromium.org <mbelshe@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-03-24 08:19:34 +0000
committermbelshe@chromium.org <mbelshe@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-03-24 08:19:34 +0000
commitc83658c33bdf286c7d4cf8f766616e297624daec (patch)
tree2435c853fe8b55dead3197e8863eb666c384b869 /net
parentdb4791c48136f73181a337e4469578e2e45dba60 (diff)
downloadchromium_src-c83658c33bdf286c7d4cf8f766616e297624daec.zip
chromium_src-c83658c33bdf286c7d4cf8f766616e297624daec.tar.gz
chromium_src-c83658c33bdf286c7d4cf8f766616e297624daec.tar.bz2
Fix to bug 39063.
The problem was the backup connect job was failed; and we didn't properly track the backup_job in the group jobs list. BUG=39063 TEST=TCPClientSocketPoolTest.BackupConnectFail Review URL: http://codereview.chromium.org/1262001 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@42440 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net')
-rw-r--r--net/socket/client_socket_pool_base.cc13
-rw-r--r--net/socket/tcp_client_socket_pool_unittest.cc92
2 files changed, 98 insertions, 7 deletions
diff --git a/net/socket/client_socket_pool_base.cc b/net/socket/client_socket_pool_base.cc
index c3172e5..d6a8caf 100644
--- a/net/socket/client_socket_pool_base.cc
+++ b/net/socket/client_socket_pool_base.cc
@@ -307,13 +307,12 @@ void ClientSocketPoolBaseHelper::OnBackupSocketTimerFired(
group.backup_job->net_log().AddEvent(NetLog::TYPE_SOCKET_BACKUP_CREATED);
SIMPLE_STATS_COUNTER("socket.backup_created");
int rv = group.backup_job->Connect();
- if (rv == ERR_IO_PENDING) {
- connecting_socket_count_++;
- group.jobs.insert(group.backup_job);
- group.backup_job = NULL;
- } else {
- OnConnectJobComplete(rv, group.backup_job);
- }
+ connecting_socket_count_++;
+ group.jobs.insert(group.backup_job);
+ ConnectJob* job = group.backup_job;
+ group.backup_job = NULL;
+ if (rv != ERR_IO_PENDING)
+ OnConnectJobComplete(rv, job);
}
void ClientSocketPoolBaseHelper::CancelRequest(
diff --git a/net/socket/tcp_client_socket_pool_unittest.cc b/net/socket/tcp_client_socket_pool_unittest.cc
index 4ef6b98..e7c8a9f 100644
--- a/net/socket/tcp_client_socket_pool_unittest.cc
+++ b/net/socket/tcp_client_socket_pool_unittest.cc
@@ -228,6 +228,7 @@ class MockClientSocketFactory : public ClientSocketFactory {
// Set a list of ClientSocketTypes to be used.
void set_client_socket_types(ClientSocketType* type_list) {
client_socket_types_ = type_list;
+ client_socket_index_ = 0;
}
private:
@@ -750,6 +751,97 @@ TEST_F(TCPClientSocketPoolTest, BackupSocketCancel) {
}
}
+// Test the case where a socket took long enough to start the creation
+// of the backup socket and never completes, and then the backup
+// connection fails.
+TEST_F(TCPClientSocketPoolTest, BackupSocketFailAfterStall) {
+ MockClientSocketFactory::ClientSocketType case_types[] = {
+ // The first socket will not connect.
+ MockClientSocketFactory::MOCK_STALLED_CLIENT_SOCKET,
+ // The second socket will fail immediately.
+ MockClientSocketFactory::MOCK_FAILING_CLIENT_SOCKET
+ };
+
+ client_socket_factory_.set_client_socket_types(case_types);
+
+ EXPECT_EQ(0, pool_->IdleSocketCount());
+
+ TestCompletionCallback callback;
+ ClientSocketHandle handle;
+ TCPSocketParams dest("www.google.com", 80, LOW, GURL(), false);
+ int rv = handle.Init("b", dest, LOW, &callback, pool_, NULL);
+ EXPECT_EQ(ERR_IO_PENDING, rv);
+ EXPECT_FALSE(handle.is_initialized());
+ EXPECT_FALSE(handle.socket());
+
+ // Create the first socket, set the timer.
+ MessageLoop::current()->RunAllPending();
+
+ // Wait for the backup socket timer to fire.
+ PlatformThread::Sleep(ClientSocketPool::kMaxConnectRetryIntervalMs);
+
+ // Let the second connect be synchronous. Otherwise, the emulated
+ // host resolution takes an extra trip through the message loop.
+ host_resolver_->set_synchronous_mode(true);
+
+ // Let the appropriate socket connect.
+ MessageLoop::current()->RunAllPending();
+
+ EXPECT_EQ(ERR_CONNECTION_FAILED, callback.WaitForResult());
+ EXPECT_FALSE(handle.is_initialized());
+ EXPECT_FALSE(handle.socket());
+ EXPECT_EQ(0, pool_->IdleSocketCount());
+ handle.Reset();
+
+ // Reset for the next case.
+ host_resolver_->set_synchronous_mode(false);
+}
+
+// Test the case where a socket took long enough to start the creation
+// of the backup socket and eventually completes, but the backup socket
+// fails.
+TEST_F(TCPClientSocketPoolTest, BackupSocketFailAfterDelay) {
+ MockClientSocketFactory::ClientSocketType case_types[] = {
+ // The first socket will connect, although delayed.
+ MockClientSocketFactory::MOCK_DELAYED_CLIENT_SOCKET,
+ // The second socket will not connect.
+ MockClientSocketFactory::MOCK_FAILING_CLIENT_SOCKET
+ };
+
+ client_socket_factory_.set_client_socket_types(case_types);
+
+ EXPECT_EQ(0, pool_->IdleSocketCount());
+
+ TestCompletionCallback callback;
+ ClientSocketHandle handle;
+ TCPSocketParams dest("www.google.com", 80, LOW, GURL(), false);
+ int rv = handle.Init("b", dest, LOW, &callback, pool_, NULL);
+ EXPECT_EQ(ERR_IO_PENDING, rv);
+ EXPECT_FALSE(handle.is_initialized());
+ EXPECT_FALSE(handle.socket());
+
+ // Create the first socket, set the timer.
+ MessageLoop::current()->RunAllPending();
+
+ // Wait for the backup socket timer to fire.
+ PlatformThread::Sleep(ClientSocketPool::kMaxConnectRetryIntervalMs);
+
+ // Let the second connect be synchronous. Otherwise, the emulated
+ // host resolution takes an extra trip through the message loop.
+ host_resolver_->set_synchronous_mode(true);
+
+ // Let the appropriate socket connect.
+ MessageLoop::current()->RunAllPending();
+
+ EXPECT_EQ(ERR_CONNECTION_FAILED, callback.WaitForResult());
+ EXPECT_FALSE(handle.is_initialized());
+ EXPECT_FALSE(handle.socket());
+ handle.Reset();
+
+ // Reset for the next case.
+ host_resolver_->set_synchronous_mode(false);
+}
+
} // namespace
} // namespace net