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

Commit 4d4a2330 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
(cherry picked from commit 5b763c13)
parent 6d66e033
Loading
Loading
Loading
Loading
+25 −3
Original line number Diff line number Diff line
@@ -425,7 +425,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());

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

    write_section_stats(requests->sectionStats(this->id), buffer);
    if (timedOut || buffer.timedOut()) {
        ALOGW("WorkerThreadSection '%s' timed out", this->name.string());
@@ -813,7 +826,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;
}

@@ -915,7 +931,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());
@@ -934,7 +950,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;
}