diff options
-rw-r--r-- | libs/binder/RpcTransportRaw.cpp | 77 |
1 files changed, 41 insertions, 36 deletions
diff --git a/libs/binder/RpcTransportRaw.cpp b/libs/binder/RpcTransportRaw.cpp index 41f4a9f2bf..a22bc6fdc9 100644 --- a/libs/binder/RpcTransportRaw.cpp +++ b/libs/binder/RpcTransportRaw.cpp @@ -43,56 +43,61 @@ public: return ret; } - status_t interruptableWriteFully(FdTrigger* fdTrigger, const void* data, size_t size) override { - const uint8_t* buffer = reinterpret_cast<const uint8_t*>(data); - const uint8_t* end = buffer + size; + template <typename Buffer, typename SendOrReceive> + status_t interruptableReadOrWrite(FdTrigger* fdTrigger, Buffer buffer, size_t size, + SendOrReceive sendOrReceiveFun, const char* funName, + int16_t event) { + const Buffer end = buffer + size; MAYBE_WAIT_IN_FLAKE_MODE; + // 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; + } + + bool first = true; status_t status; - while ((status = fdTrigger->triggerablePoll(mSocket.get(), POLLOUT)) == OK) { - ssize_t writeSize = - TEMP_FAILURE_RETRY(::send(mSocket.get(), buffer, end - buffer, MSG_NOSIGNAL)); - if (writeSize < 0) { + do { + ssize_t processSize = TEMP_FAILURE_RETRY( + sendOrReceiveFun(mSocket.get(), buffer, end - buffer, MSG_NOSIGNAL)); + + if (processSize < 0) { int savedErrno = errno; - LOG_RPC_DETAIL("RpcTransport send(): %s", strerror(savedErrno)); - return -savedErrno; - } - if (writeSize == 0) return DEAD_OBJECT; + // Still return the error on later passes, since it would expose + // a problem with polling + if (!first || (first && savedErrno != EAGAIN && savedErrno != EWOULDBLOCK)) { + LOG_RPC_DETAIL("RpcTransport %s(): %s", funName, strerror(savedErrno)); + return -savedErrno; + } + } else if (processSize == 0) { + return DEAD_OBJECT; + } else { + buffer += processSize; + if (buffer == end) { + return OK; + } + } - buffer += writeSize; - if (buffer == end) return OK; - } + if (first) first = false; + } while ((status = fdTrigger->triggerablePoll(mSocket.get(), event)) == OK); return status; } - status_t interruptableReadFully(FdTrigger* fdTrigger, void* data, size_t size) override { - uint8_t* buffer = reinterpret_cast<uint8_t*>(data); - uint8_t* end = buffer + size; - - MAYBE_WAIT_IN_FLAKE_MODE; - - status_t status; - while ((status = fdTrigger->triggerablePoll(mSocket.get(), POLLIN)) == OK) { - ssize_t readSize = - TEMP_FAILURE_RETRY(::recv(mSocket.get(), buffer, end - buffer, MSG_NOSIGNAL)); - if (readSize < 0) { - int savedErrno = errno; - LOG_RPC_DETAIL("RpcTransport recv(): %s", strerror(savedErrno)); - return -savedErrno; - } - - if (readSize == 0) return DEAD_OBJECT; // EOF + status_t interruptableWriteFully(FdTrigger* fdTrigger, const void* data, size_t size) override { + return interruptableReadOrWrite(fdTrigger, reinterpret_cast<const uint8_t*>(data), size, + send, "send", POLLOUT); + } - buffer += readSize; - if (buffer == end) return OK; - } - return status; + status_t interruptableReadFully(FdTrigger* fdTrigger, void* data, size_t size) override { + return interruptableReadOrWrite(fdTrigger, reinterpret_cast<uint8_t*>(data), size, recv, + "recv", POLLIN); } private: - android::base::unique_fd mSocket; + base::unique_fd mSocket; }; // RpcTransportCtx with TLS disabled. |