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

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

Merge "binder: retry connect() on ECONNRESET for non-blocking sockets." am:...

Merge "binder: retry connect() on ECONNRESET for non-blocking sockets." am: 0ae8394e am: 08b70b45

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

Change-Id: I29e61be4577080fe6cc4b9c700a94c2abc3b3ccf
parents 87470455 08b70b45
Loading
Loading
Loading
Loading
+29 −27
Original line number Diff line number Diff line
@@ -484,16 +484,8 @@ status_t RpcSession::setupOneSocketConnection(const RpcSocketAddress& addr,
        }

        if (0 != TEMP_FAILURE_RETRY(connect(serverFd.get(), addr.addr(), addr.addrSize()))) {
            if (errno == ECONNRESET) {
                ALOGW("Connection reset on %s", addr.toString().c_str());
                continue;
            }
            if (errno != EAGAIN && errno != EINPROGRESS) {
                int savedErrno = errno;
                ALOGE("Could not connect socket at %s: %s", addr.toString().c_str(),
                      strerror(savedErrno));
                return -savedErrno;
            }
            int connErrno = errno;
            if (connErrno == EAGAIN || connErrno == EINPROGRESS) {
                // For non-blocking sockets, connect() may return EAGAIN (for unix domain socket) or
                // EINPROGRESS (for others). Call poll() and getsockopt() to get the error.
                status_t pollStatus = mShutdownTrigger->triggerablePoll(serverFd, POLLOUT);
@@ -502,19 +494,29 @@ status_t RpcSession::setupOneSocketConnection(const RpcSocketAddress& addr,
                          statusToString(pollStatus).c_str());
                    return pollStatus;
                }
            int soError;
            socklen_t soErrorLen = sizeof(soError);
            int ret = getsockopt(serverFd.get(), SOL_SOCKET, SO_ERROR, &soError, &soErrorLen);
                // Set connErrno to the errno that connect() would have set if the fd were blocking.
                socklen_t connErrnoLen = sizeof(connErrno);
                int ret =
                        getsockopt(serverFd.get(), SOL_SOCKET, SO_ERROR, &connErrno, &connErrnoLen);
                if (ret == -1) {
                    int savedErrno = errno;
                ALOGE("Could not getsockopt() after connect() on non-blocking socket: %s",
                      strerror(savedErrno));
                    ALOGE("Could not getsockopt() after connect() on non-blocking socket: %s. "
                          "(Original error from connect() is: %s)",
                          strerror(savedErrno), strerror(connErrno));
                    return -savedErrno;
                }
            if (soError != 0) {
                ALOGE("After connect(), getsockopt() returns error for socket at %s: %s",
                      addr.toString().c_str(), strerror(soError));
                return -soError;
                // Retrieved the real connErrno as if connect() was called with a blocking socket
                // fd. Continue checking connErrno.
            }
            if (connErrno == ECONNRESET) {
                ALOGW("Connection reset on %s", addr.toString().c_str());
                continue;
            }
            // connErrno could be zero if getsockopt determines so. Hence zero-check again.
            if (connErrno != 0) {
                ALOGE("Could not connect socket at %s: %s", addr.toString().c_str(),
                      strerror(connErrno));
                return -connErrno;
            }
        }
        LOG_RPC_DETAIL("Socket at %s client with fd %d", addr.toString().c_str(), serverFd.get());