summaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/socket/client_socket_pool_base.cc13
-rw-r--r--net/socket/client_socket_pool_base_unittest.cc25
2 files changed, 38 insertions, 0 deletions
diff --git a/net/socket/client_socket_pool_base.cc b/net/socket/client_socket_pool_base.cc
index ddaa430..f584996c 100644
--- a/net/socket/client_socket_pool_base.cc
+++ b/net/socket/client_socket_pool_base.cc
@@ -342,6 +342,10 @@ void ClientSocketPoolBaseHelper::OnBackupSocketTimerFired(
void ClientSocketPoolBaseHelper::CancelRequest(
const std::string& group_name, const ClientSocketHandle* handle) {
+ // Running callbacks can cause the last outside reference to be released.
+ // Hold onto a reference.
+ scoped_refptr<ClientSocketPoolBaseHelper> ref_holder(this);
+
CHECK(ContainsKey(group_map_, group_name));
Group& group = group_map_[group_name];
@@ -480,6 +484,10 @@ void ClientSocketPoolBaseHelper::DecrementIdleCount() {
void ClientSocketPoolBaseHelper::DoReleaseSocket(const std::string& group_name,
ClientSocket* socket) {
+ // Running callbacks can cause the last outside reference to be released.
+ // Hold onto a reference.
+ scoped_refptr<ClientSocketPoolBaseHelper> ref_holder(this);
+
GroupMap::iterator i = group_map_.find(group_name);
CHECK(i != group_map_.end());
@@ -573,6 +581,10 @@ int ClientSocketPoolBaseHelper::FindTopStalledGroup(Group** group,
void ClientSocketPoolBaseHelper::OnConnectJobComplete(
int result, ConnectJob* job) {
+ // Running callbacks can cause the last outside reference to be released.
+ // Hold onto a reference.
+ scoped_refptr<ClientSocketPoolBaseHelper> ref_holder(this);
+
DCHECK_NE(ERR_IO_PENDING, result);
const std::string group_name = job->group_name();
GroupMap::iterator group_it = group_map_.find(group_name);
@@ -618,6 +630,7 @@ void ClientSocketPoolBaseHelper::OnConnectJobComplete(
}
void ClientSocketPoolBaseHelper::OnIPAddressChanged() {
+ CancelAllConnectJobs();
CloseIdleSockets();
}
diff --git a/net/socket/client_socket_pool_base_unittest.cc b/net/socket/client_socket_pool_base_unittest.cc
index bf0f96e..a694a6f 100644
--- a/net/socket/client_socket_pool_base_unittest.cc
+++ b/net/socket/client_socket_pool_base_unittest.cc
@@ -1635,6 +1635,31 @@ TEST_F(ClientSocketPoolBaseTest, ReleasedSocketReleasesToo) {
EXPECT_EQ(OK, request.WaitForResult());
}
+// http://crbug.com/44724 regression test.
+// We start releasing the pool when we flush on network change. When that
+// happens, the only active references are in the ClientSocketHandles. When a
+// ConnectJob completes and calls back into the last ClientSocketHandle, that
+// callback can release the last reference and delete the pool. After the
+// callback finishes, we go back to the stack frame within the now-deleted pool.
+// Executing any code that refers to members of the now-deleted pool can cause
+// crashes.
+TEST_F(ClientSocketPoolBaseTest, CallbackThatReleasesPool) {
+ CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup);
+ connect_job_factory_->set_job_type(TestConnectJob::kMockPendingFailingJob);
+
+ ClientSocketHandle handle;
+ TestCompletionCallback callback;
+ EXPECT_EQ(ERR_IO_PENDING,
+ InitHandle(&handle, "a", kDefaultPriority,
+ &callback, pool_, BoundNetLog()));
+
+ // Simulate flushing the pool.
+ pool_ = NULL;
+
+ // We'll call back into this now.
+ callback.WaitForResult();
+}
+
} // namespace
} // namespace net