diff options
author | 2022-07-21 00:55:10 +0000 | |
---|---|---|
committer | 2022-07-21 20:19:12 +0000 | |
commit | 9b40419e498181d9426c773aa31b6982f5f2629a (patch) | |
tree | c22270e398b7df6e955af9a958b67fcb8beb6cc9 | |
parent | 4d9b036fbb445dcd6c97393a73259b556e86760b (diff) |
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
-rw-r--r-- | libs/binder/FdTrigger.h | 1 | ||||
-rw-r--r-- | libs/binder/RpcTransportRaw.cpp | 91 | ||||
-rw-r--r-- | libs/binder/RpcTransportUtils.h | 109 |
3 files changed, 115 insertions, 86 deletions
diff --git a/libs/binder/FdTrigger.h b/libs/binder/FdTrigger.h index 5c7102e22e..a25dc117f3 100644 --- a/libs/binder/FdTrigger.h +++ b/libs/binder/FdTrigger.h @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#pragma once #include <memory> diff --git a/libs/binder/RpcTransportRaw.cpp b/libs/binder/RpcTransportRaw.cpp index 7cc58cd776..51326f6346 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 @@ public: 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 @@ public: }; 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 @@ public: }; 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: diff --git a/libs/binder/RpcTransportUtils.h b/libs/binder/RpcTransportUtils.h new file mode 100644 index 0000000000..00cb2af8c3 --- /dev/null +++ b/libs/binder/RpcTransportUtils.h @@ -0,0 +1,109 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#pragma once + +#include <android-base/unique_fd.h> +#include <poll.h> + +#include "FdTrigger.h" +#include "RpcState.h" + +namespace android { + +template <typename SendOrReceive> +status_t interruptableReadOrWrite( + int socketFd, 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(socketFd, event); status != OK) + return status; + if (!havePolled) havePolled = true; + } + } +} + +} // namespace android |