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");
 }