summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Yifan Hong <elsk@google.com> 2021-08-05 16:37:17 -0700
committer Yifan Hong <elsk@google.com> 2021-08-06 12:09:40 -0700
commitb675ffe41b574bd7a13ebbc8682cf147508b5c21 (patch)
tree563138d017c6ccd0b587876c2c8bc66133b6bce1
parent8c950421dbe8d9c2cea5e293b925b01d6f8c52da (diff)
binder: RPC uses non-blocking sockets.
With TLS, even though poll() may have returned for an FD, there may not be a complete packet available, so I/O operations within libssl may block and not interruptible by the shutdown trigger. Hence, always use non-blocking sockets. Test: binderRpcTest Bug: 195683291 Change-Id: I372e8c3bf010c672b1c4b9f7cb5b789ca20c9480
-rw-r--r--libs/binder/RpcServer.cpp6
-rw-r--r--libs/binder/RpcSession.cpp9
-rw-r--r--libs/binder/RpcTransportRaw.cpp2
-rw-r--r--libs/binder/Utils.cpp16
-rw-r--r--libs/binder/Utils.h5
5 files changed, 31 insertions, 7 deletions
diff --git a/libs/binder/RpcServer.cpp b/libs/binder/RpcServer.cpp
index 66483edffb..a0c508be03 100644
--- a/libs/binder/RpcServer.cpp
+++ b/libs/binder/RpcServer.cpp
@@ -168,7 +168,7 @@ void RpcServer::join() {
status_t status;
while ((status = mShutdownTrigger->triggerablePoll(mServer, POLLIN)) == OK) {
unique_fd clientFd(TEMP_FAILURE_RETRY(
- accept4(mServer.get(), nullptr, nullptr /*length*/, SOCK_CLOEXEC)));
+ accept4(mServer.get(), nullptr, nullptr /*length*/, SOCK_CLOEXEC | SOCK_NONBLOCK)));
if (clientFd < 0) {
ALOGE("Could not accept4 socket: %s", strerror(errno));
@@ -388,8 +388,8 @@ status_t RpcServer::setupSocketServer(const RpcSocketAddress& addr) {
LOG_RPC_DETAIL("Setting up socket server %s", addr.toString().c_str());
LOG_ALWAYS_FATAL_IF(hasServer(), "Each RpcServer can only have one server.");
- unique_fd serverFd(
- TEMP_FAILURE_RETRY(socket(addr.addr()->sa_family, SOCK_STREAM | SOCK_CLOEXEC, 0)));
+ unique_fd serverFd(TEMP_FAILURE_RETRY(
+ socket(addr.addr()->sa_family, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0)));
if (serverFd == -1) {
int savedErrno = errno;
ALOGE("Could not create socket: %s", strerror(savedErrno));
diff --git a/libs/binder/RpcSession.cpp b/libs/binder/RpcSession.cpp
index c756f2e8fb..73061b8948 100644
--- a/libs/binder/RpcSession.cpp
+++ b/libs/binder/RpcSession.cpp
@@ -39,6 +39,7 @@
#include "RpcSocketAddress.h"
#include "RpcState.h"
#include "RpcWireFormat.h"
+#include "Utils.h"
#ifdef __GLIBC__
extern "C" pid_t gettid();
@@ -134,6 +135,10 @@ status_t RpcSession::setupPreconnectedClient(unique_fd fd, std::function<unique_
fd = request();
if (!fd.ok()) return BAD_VALUE;
}
+ if (auto res = setNonBlocking(fd); !res.ok()) {
+ ALOGE("setupPreconnectedClient: %s", res.error().message().c_str());
+ return res.error().code() == 0 ? UNKNOWN_ERROR : -res.error().code();
+ }
return initAndAddConnection(std::move(fd), sessionId, incoming);
});
}
@@ -470,8 +475,8 @@ status_t RpcSession::setupOneSocketConnection(const RpcSocketAddress& addr,
for (size_t tries = 0; tries < 5; tries++) {
if (tries > 0) usleep(10000);
- unique_fd serverFd(
- TEMP_FAILURE_RETRY(socket(addr.addr()->sa_family, SOCK_STREAM | SOCK_CLOEXEC, 0)));
+ unique_fd serverFd(TEMP_FAILURE_RETRY(
+ socket(addr.addr()->sa_family, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0)));
if (serverFd == -1) {
int savedErrno = errno;
ALOGE("Could not create socket at %s: %s", addr.toString().c_str(),
diff --git a/libs/binder/RpcTransportRaw.cpp b/libs/binder/RpcTransportRaw.cpp
index 995c54234f..46170f7f7a 100644
--- a/libs/binder/RpcTransportRaw.cpp
+++ b/libs/binder/RpcTransportRaw.cpp
@@ -50,7 +50,7 @@ public:
return ret;
}
Result<size_t> peek(void *buf, size_t size) override {
- ssize_t ret = TEMP_FAILURE_RETRY(::recv(mSocket.get(), buf, size, MSG_PEEK | MSG_DONTWAIT));
+ ssize_t ret = TEMP_FAILURE_RETRY(::recv(mSocket.get(), buf, size, MSG_PEEK));
if (ret < 0) {
return ErrnoError() << "recv(MSG_PEEK)";
}
diff --git a/libs/binder/Utils.cpp b/libs/binder/Utils.cpp
index 90a4502ec5..d2a5be1102 100644
--- a/libs/binder/Utils.cpp
+++ b/libs/binder/Utils.cpp
@@ -18,10 +18,24 @@
#include <string.h>
+using android::base::ErrnoError;
+using android::base::Result;
+
namespace android {
void zeroMemory(uint8_t* data, size_t size) {
memset(data, 0, size);
}
-} // namespace android
+Result<void> setNonBlocking(android::base::borrowed_fd fd) {
+ int flags = TEMP_FAILURE_RETRY(fcntl(fd.get(), F_GETFL));
+ if (flags == -1) {
+ return ErrnoError() << "Could not get flags for fd";
+ }
+ if (int ret = TEMP_FAILURE_RETRY(fcntl(fd.get(), F_SETFL, flags | O_NONBLOCK)); ret == -1) {
+ return ErrnoError() << "Could not set non-blocking flag for fd";
+ }
+ return {};
+}
+
+} // namespace android
diff --git a/libs/binder/Utils.h b/libs/binder/Utils.h
index f94b158404..1e383da095 100644
--- a/libs/binder/Utils.h
+++ b/libs/binder/Utils.h
@@ -17,9 +17,14 @@
#include <cstdint>
#include <stddef.h>
+#include <android-base/result.h>
+#include <android-base/unique_fd.h>
+
namespace android {
// avoid optimizations
void zeroMemory(uint8_t* data, size_t size);
+android::base::Result<void> setNonBlocking(android::base::borrowed_fd fd);
+
} // namespace android