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

Commit 2b3ebaf5 authored by Tom Cherry's avatar Tom Cherry
Browse files

SocketClient: don't ignore SIGPIPE

1) All current users are better off ignoring SIGPIPE at the beginning
   of their process instead of ignoring it just for SocketClient
2) This isn't thread safe if users did want it, since sigaction()
   ignores SIGPIPE for the entire process
3) This costs 5-10% of logd CPU time when logcat is reading logs

Also clean up the error handling in SocketClient::sendDataLockedv().

Test: kill logcat and see that logd doesn't crash
Test: run simpleperf and see that no cycles are going to sigaction
Change-Id: I6532c8a0d71338e534411707b9a9bd785145c730
parent fcaed0ef
Loading
Loading
Loading
Loading
+16 −35
Original line number Diff line number Diff line
@@ -201,50 +201,31 @@ int SocketClient::sendDataLockedv(struct iovec *iov, int iovcnt) {
        return 0;
    }

    int ret = 0;
    int e = 0; // SLOGW and sigaction are not inert regarding errno
    int current = 0;

    struct sigaction new_action, old_action;
    memset(&new_action, 0, sizeof(new_action));
    new_action.sa_handler = SIG_IGN;
    sigaction(SIGPIPE, &new_action, &old_action);

    for (;;) {
        ssize_t rc = TEMP_FAILURE_RETRY(
            writev(mSocket, iov + current, iovcnt - current));
        ssize_t rc = TEMP_FAILURE_RETRY(writev(mSocket, iov + current, iovcnt - current));

        if (rc == 0) {
            errno = EIO;
            SLOGW("0 length write :(");
            return -1;
        } else if (rc < 0) {
            SLOGW("write error (%s)", strerror(errno));
            return -1;
        }

        if (rc > 0) {
        size_t written = rc;
            while ((current < iovcnt) && (written >= iov[current].iov_len)) {
        while (current < iovcnt && written >= iov[current].iov_len) {
            written -= iov[current].iov_len;
            current++;
        }
        if (current == iovcnt) {
                break;
            return 0;
        }
        iov[current].iov_base = (char*)iov[current].iov_base + written;
        iov[current].iov_len -= written;
            continue;
    }

        if (rc == 0) {
            e = EIO;
            SLOGW("0 length write :(");
        } else {
            e = errno;
            SLOGW("write error (%s)", strerror(e));
        }
        ret = -1;
        break;
    }

    sigaction(SIGPIPE, &old_action, &new_action);

    if (e != 0) {
        errno = e;
    }
    return ret;
}

void SocketClient::incRef() {
+2 −0
Original line number Diff line number Diff line
@@ -218,6 +218,8 @@ static int issueReinit() {
// logging plugins like auditd and restart control. Additional
// transitory per-client threads are created for each reader.
int main(int argc, char* argv[]) {
    // We want EPIPE when a reader disconnects, not to terminate logd.
    signal(SIGPIPE, SIG_IGN);
    // logd is written under the assumption that the timezone is UTC.
    // If TZ is not set, persist.sys.timezone is looked up in some time utility
    // libc functions, including mktime. It confuses the logd time handling,