summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libs/binder/RpcTransportRaw.cpp77
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.