Fix CPU spinning on failed connection attempt.
Bug: 74423413
Change-Id: I8ada9923f38d325a5dd74c799c61a15bc791b588
diff --git a/src/ipc/client_impl.cc b/src/ipc/client_impl.cc
index 0560244..d34a8f0 100644
--- a/src/ipc/client_impl.cc
+++ b/src/ipc/client_impl.cc
@@ -164,7 +164,7 @@
}
if (!frame_deserializer_.EndReceive(rsize)) {
// The endpoint tried to send a frame that is way too large.
- return sock_->Shutdown(); // In turn will trigger an OnDisconnect().
+ return sock_->Shutdown(true); // In turn will trigger an OnDisconnect().
// TODO(fmayer): check this.
}
} while (rsize > 0);
diff --git a/src/ipc/unix_socket.cc b/src/ipc/unix_socket.cc
index 4dc1ffb..463682b 100644
--- a/src/ipc/unix_socket.cc
+++ b/src/ipc/unix_socket.cc
@@ -209,7 +209,7 @@
UnixSocket::~UnixSocket() {
// The implicit dtor of |weak_ptr_factory_| will no-op pending callbacks.
- Shutdown();
+ Shutdown(true);
}
// Called only by the Connect() static constructor.
@@ -289,6 +289,7 @@
return event_listener_->OnConnect(this, true /* connected */);
}
last_error_ = sock_err;
+ Shutdown(false);
return event_listener_->OnConnect(this, false /* connected */);
}
@@ -370,23 +371,26 @@
// happened.
last_error_ = errno;
PERFETTO_DPLOG("sendmsg() failed");
- Shutdown();
+ Shutdown(true);
return false;
}
-void UnixSocket::Shutdown() {
+void UnixSocket::Shutdown(bool notify) {
base::WeakPtr<UnixSocket> weak_ptr = weak_ptr_factory_.GetWeakPtr();
- if (state_ == State::kConnected) {
- task_runner_->PostTask([weak_ptr]() {
- if (weak_ptr)
- weak_ptr->event_listener_->OnDisconnect(weak_ptr.get());
- });
- } else if (state_ == State::kConnecting) {
- task_runner_->PostTask([weak_ptr]() {
- if (weak_ptr)
- weak_ptr->event_listener_->OnConnect(weak_ptr.get(), false);
- });
+ if (notify) {
+ if (state_ == State::kConnected) {
+ task_runner_->PostTask([weak_ptr]() {
+ if (weak_ptr)
+ weak_ptr->event_listener_->OnDisconnect(weak_ptr.get());
+ });
+ } else if (state_ == State::kConnecting) {
+ task_runner_->PostTask([weak_ptr]() {
+ if (weak_ptr)
+ weak_ptr->event_listener_->OnConnect(weak_ptr.get(), false);
+ });
+ }
}
+
if (fd_) {
shutdown(*fd_, SHUT_RDWR);
task_runner_->RemoveFileDescriptorWatch(*fd_);
@@ -419,7 +423,7 @@
}
if (sz <= 0) {
last_error_ = errno;
- Shutdown();
+ Shutdown(true);
return 0;
}
PERFETTO_CHECK(static_cast<size_t>(sz) <= len);
@@ -444,7 +448,7 @@
for (size_t i = 0; fds && i < fds_len; ++i)
close(fds[i]);
last_error_ = EMSGSIZE;
- Shutdown();
+ Shutdown(true);
return 0;
}
@@ -469,6 +473,9 @@
}
void UnixSocket::NotifyConnectionState(bool success) {
+ if (!success)
+ Shutdown(false);
+
base::WeakPtr<UnixSocket> weak_ptr = weak_ptr_factory_.GetWeakPtr();
task_runner_->PostTask([weak_ptr, success]() {
if (weak_ptr)
diff --git a/src/ipc/unix_socket.h b/src/ipc/unix_socket.h
index f4cec1b..dc83d53 100644
--- a/src/ipc/unix_socket.h
+++ b/src/ipc/unix_socket.h
@@ -143,7 +143,7 @@
// Shuts down the current connection, if any. If the socket was Listen()-ing,
// stops listening. The socket goes back to kNotInitialized state, so it can
// be reused with Listen() or Connect().
- void Shutdown();
+ void Shutdown(bool notify);
// Returns true is the message was queued, false if there was no space in the
// output buffer, in which case the client should retry or give up.
diff --git a/src/ipc/unix_socket_unittest.cc b/src/ipc/unix_socket_unittest.cc
index a803c92..a2bdb58 100644
--- a/src/ipc/unix_socket_unittest.cc
+++ b/src/ipc/unix_socket_unittest.cc
@@ -99,7 +99,7 @@
.WillOnce(
Invoke([this, srv_did_shutdown](UnixSocket*, UnixSocket* new_conn) {
EXPECT_CALL(event_listener_, OnDisconnect(new_conn));
- new_conn->Shutdown();
+ new_conn->Shutdown(true);
srv_did_shutdown();
}));
@@ -161,7 +161,7 @@
auto cli_disconnected = task_runner_.CreateCheckpoint("cli_disconnected");
EXPECT_CALL(event_listener_, OnDisconnect(cli.get()))
.WillOnce(InvokeWithoutArgs(cli_disconnected));
- cli->Shutdown();
+ cli->Shutdown(true);
char msg[4];
ASSERT_EQ(0u, cli->Receive(&msg, sizeof(msg)));
ASSERT_EQ("", cli->ReceiveString());
@@ -169,7 +169,7 @@
ASSERT_EQ("", srv_conn->ReceiveString());
ASSERT_FALSE(cli->Send("foo"));
ASSERT_FALSE(srv_conn->Send("bar"));
- srv->Shutdown();
+ srv->Shutdown(true);
task_runner_.RunUntilCheckpoint("cli_disconnected");
task_runner_.RunUntilCheckpoint("srv_disconnected");
}