Parse postinstall program progress updates.
In Android postinstall is expected to take a long time in common cases.
This patch allows the postinstall program to report back to the updater
a progress indication, which will then be forwarded to all the clients
listening. These progress updates are part of the FINALIZING status.
Bug: 27880754
TEST=Added unittests. Deployed an update to an edison-eng and post-install reported progress back with the postinstall_example.
Change-Id: I35f96b92f090219c54cca48d8ab07c54cf8b4ab1
diff --git a/common/subprocess.cc b/common/subprocess.cc
index 1bfb911..9738b1d 100644
--- a/common/subprocess.cc
+++ b/common/subprocess.cc
@@ -33,6 +33,8 @@
#include <brillo/process.h>
#include <brillo/secure_blob.h>
+#include "update_engine/common/utils.h"
+
using brillo::MessageLoop;
using std::string;
using std::unique_ptr;
@@ -114,26 +116,21 @@
void Subprocess::OnStdoutReady(SubprocessRecord* record) {
char buf[1024];
- ssize_t rc = 0;
+ size_t bytes_read;
do {
- rc = HANDLE_EINTR(read(record->stdout_fd, buf, arraysize(buf)));
- if (rc < 0) {
- // EAGAIN and EWOULDBLOCK are normal return values when there's no more
- // input as we are in non-blocking mode.
- if (errno != EWOULDBLOCK && errno != EAGAIN) {
- PLOG(ERROR) << "Error reading fd " << record->stdout_fd;
- MessageLoop::current()->CancelTask(record->stdout_task_id);
- record->stdout_task_id = MessageLoop::kTaskIdNull;
- }
- } else if (rc == 0) {
- // A value of 0 means that the child closed its end of the pipe and there
- // is nothing else to read from stdout.
+ bytes_read = 0;
+ bool eof;
+ bool ok = utils::ReadAll(
+ record->stdout_fd, buf, arraysize(buf), &bytes_read, &eof);
+ record->stdout.append(buf, bytes_read);
+ if (!ok || eof) {
+ // There was either an error or an EOF condition, so we are done watching
+ // the file descriptor.
MessageLoop::current()->CancelTask(record->stdout_task_id);
record->stdout_task_id = MessageLoop::kTaskIdNull;
- } else {
- record->stdout.append(buf, rc);
+ return;
}
- } while (rc > 0);
+ } while (bytes_read);
}
void Subprocess::ChildExitedCallback(const siginfo_t& info) {