diff options
author | Boleyn Su <boleynsu@google.com> | 2020-02-27 03:22:53 +0900 |
---|---|---|
committer | Mike Ma <yanmin@google.com> | 2020-03-04 23:03:40 -0800 |
commit | 1c8ed242b578c2fc526511508bda8ae22da2e9c4 (patch) | |
tree | 843b4a69f5f38a77d2e353f90ca6597c7ae7ab40 | |
parent | f7ed9bc589774fcc911321bae5c6521397e95aef (diff) |
Fix a race conditon in `incident`.
`incident` may exit too early, which leads to data lost. This commit
fixes it.
Bug: 144821874
Test: atest com.android.server.cts.IncidentdTest
Change-Id: Ib73118cb690a8247049b5685ed0b227dad63f752
-rw-r--r-- | cmds/incident/main.cpp | 32 |
1 files changed, 17 insertions, 15 deletions
diff --git a/cmds/incident/main.cpp b/cmds/incident/main.cpp index eb2b98a666b9..d6c6c39dd1d8 100644 --- a/cmds/incident/main.cpp +++ b/cmds/incident/main.cpp @@ -52,9 +52,13 @@ public: virtual Status onReportServiceStatus(const String16& service, int32_t status); virtual Status onReportFinished(); virtual Status onReportFailed(); + + int getExitCodeOrElse(int defaultCode); + private: + int mExitCode; }; -StatusListener::StatusListener() +StatusListener::StatusListener(): mExitCode(-1) { } @@ -89,7 +93,7 @@ StatusListener::onReportFinished() { fprintf(stderr, "done\n"); ALOGD("done\n"); - exit(0); + mExitCode = 0; return Status::ok(); } @@ -98,10 +102,15 @@ StatusListener::onReportFailed() { fprintf(stderr, "failed\n"); ALOGD("failed\n"); - exit(1); + mExitCode = 1; return Status::ok(); } +int +StatusListener::getExitCodeOrElse(int defaultCode) { + return mExitCode == -1 ? defaultCode : mExitCode; +} + // ================================================================================ static void section_list(FILE* out) { IncidentSection sections[INCIDENT_SECTION_COUNT]; @@ -201,20 +210,13 @@ parse_receiver_arg(const string& arg, string* pkg, string* cls) static int stream_output(const int read_fd, const int write_fd) { while (true) { - uint8_t buf[4096]; - ssize_t amt = TEMP_FAILURE_RETRY(read(read_fd, buf, sizeof(buf))); + int amt = splice(read_fd, NULL, write_fd, NULL, 4096, 0); if (amt < 0) { - break; - } else if (amt == 0) { - break; - } - - ssize_t wamt = TEMP_FAILURE_RETRY(write(write_fd, buf, amt)); - if (wamt != amt) { return errno; + } else if (amt == 0) { + return 0; } } - return 0; } // ================================================================================ @@ -384,7 +386,7 @@ main(int argc, char** argv) // Wait for the result and print out the data they send. //IPCThreadState::self()->joinThreadPool(); - return stream_output(fds[0], STDOUT_FILENO); + return listener->getExitCodeOrElse(stream_output(fds[0], STDOUT_FILENO)); } else if (destination == DEST_DUMPSTATE) { // Call into the service sp<StatusListener> listener(new StatusListener()); @@ -393,7 +395,7 @@ main(int argc, char** argv) fprintf(stderr, "reportIncident returned \"%s\"\n", status.toString8().string()); return 1; } - return stream_output(fds[0], STDOUT_FILENO); + return listener->getExitCodeOrElse(stream_output(fds[0], STDOUT_FILENO)); } else { status = service->reportIncident(args); if (!status.isOk()) { |