libbinder: move interruptableReadOrWrite to new file
Moves interruptableReadOrWrite to a new RpcTransportUtils.h
file so it can be used by multiple transports.
Bug: 224644083
Test: m
Change-Id: Ife48519ab5c6a99d5fbbcd4ad9e6c3fe517dd0ba
diff --git a/libs/binder/RpcTransportRaw.cpp b/libs/binder/RpcTransportRaw.cpp
index 7cc58cd..51326f6 100644
--- a/libs/binder/RpcTransportRaw.cpp
+++ b/libs/binder/RpcTransportRaw.cpp
@@ -24,6 +24,7 @@
#include "FdTrigger.h"
#include "RpcState.h"
+#include "RpcTransportUtils.h"
namespace android {
@@ -55,90 +56,6 @@
return OK;
}
- template <typename SendOrReceive>
- status_t interruptableReadOrWrite(
- FdTrigger* fdTrigger, iovec* iovs, int niovs, SendOrReceive sendOrReceiveFun,
- const char* funName, int16_t event,
- const std::optional<android::base::function_ref<status_t()>>& altPoll) {
- MAYBE_WAIT_IN_FLAKE_MODE;
-
- if (niovs < 0) {
- return BAD_VALUE;
- }
-
- // Since we didn't poll, we need to manually check to see if it was triggered. Otherwise, we
- // may never know we should be shutting down.
- if (fdTrigger->isTriggered()) {
- return DEAD_OBJECT;
- }
-
- // If iovs has one or more empty vectors at the end and
- // we somehow advance past all the preceding vectors and
- // pass some or all of the empty ones to sendmsg/recvmsg,
- // the call will return processSize == 0. In that case
- // we should be returning OK but instead return DEAD_OBJECT.
- // To avoid this problem, we make sure here that the last
- // vector at iovs[niovs - 1] has a non-zero length.
- while (niovs > 0 && iovs[niovs - 1].iov_len == 0) {
- niovs--;
- }
- if (niovs == 0) {
- // The vectors are all empty, so we have nothing to send.
- return OK;
- }
-
- bool havePolled = false;
- while (true) {
- ssize_t processSize = sendOrReceiveFun(iovs, niovs);
- if (processSize < 0) {
- int savedErrno = errno;
-
- // Still return the error on later passes, since it would expose
- // a problem with polling
- if (havePolled || (savedErrno != EAGAIN && savedErrno != EWOULDBLOCK)) {
- LOG_RPC_DETAIL("RpcTransport %s(): %s", funName, strerror(savedErrno));
- return -savedErrno;
- }
- } else if (processSize == 0) {
- return DEAD_OBJECT;
- } else {
- while (processSize > 0 && niovs > 0) {
- auto& iov = iovs[0];
- if (static_cast<size_t>(processSize) < iov.iov_len) {
- // Advance the base of the current iovec
- iov.iov_base = reinterpret_cast<char*>(iov.iov_base) + processSize;
- iov.iov_len -= processSize;
- break;
- }
-
- // The current iovec was fully written
- processSize -= iov.iov_len;
- iovs++;
- niovs--;
- }
- if (niovs == 0) {
- LOG_ALWAYS_FATAL_IF(processSize > 0,
- "Reached the end of iovecs "
- "with %zd bytes remaining",
- processSize);
- return OK;
- }
- }
-
- if (altPoll) {
- if (status_t status = (*altPoll)(); status != OK) return status;
- if (fdTrigger->isTriggered()) {
- return DEAD_OBJECT;
- }
- } else {
- if (status_t status = fdTrigger->triggerablePoll(mSocket.get(), event);
- status != OK)
- return status;
- if (!havePolled) havePolled = true;
- }
- }
- }
-
status_t interruptableWriteFully(
FdTrigger* fdTrigger, iovec* iovs, int niovs,
const std::optional<android::base::function_ref<status_t()>>& altPoll,
@@ -198,7 +115,8 @@
};
return TEMP_FAILURE_RETRY(sendmsg(mSocket.get(), &msg, MSG_NOSIGNAL));
};
- return interruptableReadOrWrite(fdTrigger, iovs, niovs, send, "sendmsg", POLLOUT, altPoll);
+ return interruptableReadOrWrite(mSocket.get(), fdTrigger, iovs, niovs, send, "sendmsg",
+ POLLOUT, altPoll);
}
status_t interruptableReadFully(
@@ -255,7 +173,8 @@
};
return TEMP_FAILURE_RETRY(recvmsg(mSocket.get(), &msg, MSG_NOSIGNAL));
};
- return interruptableReadOrWrite(fdTrigger, iovs, niovs, recv, "recvmsg", POLLIN, altPoll);
+ return interruptableReadOrWrite(mSocket.get(), fdTrigger, iovs, niovs, recv, "recvmsg",
+ POLLIN, altPoll);
}
private: