Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit bca0bde4 authored by Yifan Hong's avatar Yifan Hong Committed by Automerger Merge Worker
Browse files

Merge "binder: FdTrigger ensure POLLERR / POLLNVAL is checked" am: 82db3188...

Merge "binder: FdTrigger ensure POLLERR / POLLNVAL is checked" am: 82db3188 am: 28f0c8d1 am: e43b6d23 am: 1e72c716

Original change: https://android-review.googlesource.com/c/platform/frameworks/native/+/1835920

Change-Id: I4c8c10321b1439ee618571b268618c2a52afde04
parents 67083e5e 1e72c716
Loading
Loading
Loading
Loading
+49 −15
Original line number Original line Diff line number Diff line
@@ -17,11 +17,13 @@
#define LOG_TAG "FdTrigger"
#define LOG_TAG "FdTrigger"
#include <log/log.h>
#include <log/log.h>


#include "FdTrigger.h"

#include <poll.h>
#include <poll.h>


#include <android-base/macros.h>
#include <android-base/macros.h>


#include "FdTrigger.h"
#include "RpcState.h"
namespace android {
namespace android {


std::unique_ptr<FdTrigger> FdTrigger::make() {
std::unique_ptr<FdTrigger> FdTrigger::make() {
@@ -42,21 +44,53 @@ bool FdTrigger::isTriggered() {
}
}


status_t FdTrigger::triggerablePoll(base::borrowed_fd fd, int16_t event) {
status_t FdTrigger::triggerablePoll(base::borrowed_fd fd, int16_t event) {
    while (true) {
    LOG_ALWAYS_FATAL_IF(event == 0, "triggerablePoll %d with event 0 is not allowed", fd.get());
    pollfd pfd[]{{.fd = fd.get(), .events = static_cast<int16_t>(event), .revents = 0},
    pollfd pfd[]{{.fd = fd.get(), .events = static_cast<int16_t>(event), .revents = 0},
                 {.fd = mRead.get(), .events = 0, .revents = 0}};
                 {.fd = mRead.get(), .events = 0, .revents = 0}};
    int ret = TEMP_FAILURE_RETRY(poll(pfd, arraysize(pfd), -1));
    int ret = TEMP_FAILURE_RETRY(poll(pfd, arraysize(pfd), -1));
    if (ret < 0) {
    if (ret < 0) {
        return -errno;
        return -errno;
    }
    }
        if (ret == 0) {
    LOG_ALWAYS_FATAL_IF(ret == 0, "poll(%d) returns 0 with infinite timeout", fd.get());
            continue;

        }
    // At least one FD has events. Check them.

    // Detect explicit trigger(): DEAD_OBJECT
    if (pfd[1].revents & POLLHUP) {
    if (pfd[1].revents & POLLHUP) {
        return DEAD_OBJECT;
        return DEAD_OBJECT;
    }
    }
        return pfd[0].revents & event ? OK : DEAD_OBJECT;
    // See unknown flags in trigger FD's revents (POLLERR / POLLNVAL).
    // Treat this error condition as UNKNOWN_ERROR.
    if (pfd[1].revents != 0) {
        ALOGE("Unknown revents on trigger FD %d: revents = %d", pfd[1].fd, pfd[1].revents);
        return UNKNOWN_ERROR;
    }

    // pfd[1].revents is 0, hence pfd[0].revents must be set, and only possible values are
    // a subset of event | POLLHUP | POLLERR | POLLNVAL.

    // POLLNVAL: invalid FD number, e.g. not opened.
    if (pfd[0].revents & POLLNVAL) {
        return BAD_VALUE;
    }

    // Error condition. It wouldn't be possible to do I/O on |fd| afterwards.
    // Note: If this is the write end of a pipe then POLLHUP may also be set simultaneously. We
    //   still want DEAD_OBJECT in this case.
    if (pfd[0].revents & POLLERR) {
        LOG_RPC_DETAIL("poll() incoming FD %d results in revents = %d", pfd[0].fd, pfd[0].revents);
        return DEAD_OBJECT;
    }

    // Success condition; event flag(s) set. Even though POLLHUP may also be set,
    // treat it as a success condition to ensure data is drained.
    if (pfd[0].revents & event) {
        return OK;
    }
    }

    // POLLHUP: Peer closed connection. Treat as DEAD_OBJECT.
    // This is a very common case, so don't log.
    return DEAD_OBJECT;
}
}


} // namespace android
} // namespace android