rpc_binder: Properly shut down on socketpair() EOF

FdTrigger::triggerablePoll returns OK on POLLIN (higher priority)
and DEAD_OBJECT on POLLHUP (lower priority). Unlike INET or vsock,
socketpair() sockets trigger POLLIN|POLLHUP on EOF and EOF is detected
by recvmsg() returning zero bytes.

Adjust the server accept loop to take this into account and correctly
break out of the loop.

Bug: 250685929
Test: cleanly shut down UDS bootstrap RpcServer
Change-Id: I56d6a67373f16b5b1bdc167de94a7252bedca8e2
diff --git a/libs/binder/RpcServer.cpp b/libs/binder/RpcServer.cpp
index d47e4f0..0d06e9e 100644
--- a/libs/binder/RpcServer.cpp
+++ b/libs/binder/RpcServer.cpp
@@ -204,11 +204,15 @@
     iovec iov{&zero, sizeof(zero)};
     std::vector<std::variant<base::unique_fd, base::borrowed_fd>> fds;
 
-    if (receiveMessageFromSocket(server.mServer, &iov, 1, &fds) < 0) {
+    ssize_t num_bytes = receiveMessageFromSocket(server.mServer, &iov, 1, &fds);
+    if (num_bytes < 0) {
         int savedErrno = errno;
         ALOGE("Failed recvmsg: %s", strerror(savedErrno));
         return -savedErrno;
     }
+    if (num_bytes == 0) {
+        return DEAD_OBJECT;
+    }
     if (fds.size() != 1) {
         ALOGE("Expected exactly one fd from recvmsg, got %zu", fds.size());
         return -EINVAL;
@@ -243,8 +247,11 @@
         socklen_t addrLen = addr.size();
 
         RpcTransportFd clientSocket;
-        if (mAcceptFn(*this, &clientSocket) != OK) {
-            continue;
+        if ((status = mAcceptFn(*this, &clientSocket)) != OK) {
+            if (status == DEAD_OBJECT)
+                break;
+            else
+                continue;
         }
 
         LOG_RPC_DETAIL("accept on fd %d yields fd %d", mServer.fd.get(), clientSocket.fd.get());