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

Commit 5b763c13 authored by Kweku Adams's avatar Kweku Adams
Browse files

Handling potential SIGPIPE signals.

There are cases where dumping Java traces times out and then later tries
to write to a closed pipe, causing incidentd to crash. This introduces a
handler for the SIGPIPE signal so it doesn't crash due to a closed pipe.

Bug: 111729299
Test: lower section timeout to 5 seconds and make sure incident service
doesn't crash

Change-Id: I868aba1ae21a50ae76977e0e09e782cf94198473
parent 2518b289
Loading
Loading
Loading
Loading
+25 −3
Original line number Diff line number Diff line
@@ -407,7 +407,19 @@ WorkerThreadSection::WorkerThreadSection(int id, const int64_t timeoutMs, bool u

WorkerThreadSection::~WorkerThreadSection() {}

void sigpipe_handler(int signum) {
    if (signum == SIGPIPE) {
        ALOGE("Wrote to a broken pipe\n");
    } else {
        ALOGE("Received unexpected signal: %d\n", signum);
    }
}

static void* worker_thread_func(void* cookie) {
    // Don't crash the service if we write to a closed pipe (which can happen if
    // dumping times out).
    signal(SIGPIPE, sigpipe_handler);

    WorkerThreadData* data = (WorkerThreadData*)cookie;
    status_t err = data->section->BlockingCall(data->pipe.writeFd().get());

@@ -486,6 +498,7 @@ status_t WorkerThreadSection::Execute(ReportRequestSet* requests) const {
            }
        }
    }

    write_section_stats(requests->sectionStats(this->id), buffer);
    if (timedOut || buffer.timedOut()) {
        ALOGW("[%s] timed out", this->name.string());
@@ -773,7 +786,10 @@ status_t LogSection::BlockingCall(int pipeWriteFd) const {
        }
    }
    gLastLogsRetrieved[mLogID] = lastTimestamp;
    proto.flush(pipeWriteFd);
    if (!proto.flush(pipeWriteFd) && errno == EPIPE) {
        ALOGE("[%s] wrote to a broken pipe\n", this->name.string());
        return EPIPE;
    }
    return NO_ERROR;
}

@@ -875,7 +891,7 @@ status_t TombstoneSection::BlockingCall(int pipeWriteFd) const {
            break;
        }
        if (cStatus != NO_ERROR) {
            ALOGE("TombstoneSection '%s' child had an issue: %s\n", this->name.string(), strerror(-cStatus));
            ALOGE("[%s] child had an issue: %s\n", this->name.string(), strerror(-cStatus));
        }

        auto dump = std::make_unique<char[]>(buffer.size());
@@ -894,7 +910,13 @@ status_t TombstoneSection::BlockingCall(int pipeWriteFd) const {
        dumpPipe.readFd().reset();
    }

    proto.flush(pipeWriteFd);
    if (!proto.flush(pipeWriteFd) && errno == EPIPE) {
        ALOGE("[%s] wrote to a broken pipe\n", this->name.string());
        if (err != NO_ERROR) {
            return EPIPE;
        }
    }

    return err;
}