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

Commit 21cfc8b6 authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge "Use android::base::Pipe."

parents 52db3dc1 6fcd208d
Loading
Loading
Loading
Loading
+49 −61
Original line number Diff line number Diff line
@@ -292,6 +292,11 @@ int SetUpNonAbUpdateCommands(const std::string& package, ZipArchiveHandle zip, i
    return INSTALL_ERROR;
  }

  // When executing the update binary contained in the package, the arguments passed are:
  //   - the version number for this interface
  //   - an FD to which the program can write in order to update the progress bar.
  //   - the name of the package zip file.
  //   - an optional argument "retry" if this update is a retry of a failed update attempt.
  *cmd = {
    binary_path,
    std::to_string(kRecoveryApiVersion),
@@ -334,75 +339,56 @@ static int try_update_binary(const std::string& package, ZipArchiveHandle zip, b

  ReadSourceTargetBuild(metadata, log_buffer);

  int pipefd[2];
  pipe(pipefd);
  std::vector<std::string> args;
  if (int update_status =
          is_ab ? SetUpAbUpdateCommands(package, zip, pipefd[1], &args)
                : SetUpNonAbUpdateCommands(package, zip, retry_count, pipefd[1], &args);
      update_status != 0) {
    close(pipefd[0]);
    close(pipefd[1]);
    log_buffer->push_back(android::base::StringPrintf("error: %d", kUpdateBinaryCommandFailure));
    return update_status;
  // The updater in child process writes to the pipe to communicate with recovery.
  android::base::unique_fd pipe_read, pipe_write;
  if (!android::base::Pipe(&pipe_read, &pipe_write)) {
    PLOG(ERROR) << "Failed to create pipe for updater-recovery communication";
    return INSTALL_CORRUPT;
  }

  // When executing the update binary contained in the package, the
  // arguments passed are:
  //
  //   - the version number for this interface
  //
  //   - an FD to which the program can write in order to update the
  //     progress bar.  The program can write single-line commands:
  // The updater-recovery communication protocol.
  //
  //   progress <frac> <secs>
  //            fill up the next <frac> part of of the progress bar
  //            over <secs> seconds.  If <secs> is zero, use
  //            set_progress commands to manually control the
  //            progress of this segment of the bar.
  //       fill up the next <frac> part of of the progress bar over <secs> seconds. If <secs> is
  //       zero, use `set_progress` commands to manually control the progress of this segment of the
  //       bar.
  //
  //   set_progress <frac>
  //            <frac> should be between 0.0 and 1.0; sets the
  //            progress bar within the segment defined by the most
  //            recent progress command.
  //       <frac> should be between 0.0 and 1.0; sets the progress bar within the segment defined by
  //       the most recent progress command.
  //
  //   ui_print <string>
  //       display <string> on the screen.
  //
  //   wipe_cache
  //            a wipe of cache will be performed following a successful
  //            installation.
  //       a wipe of cache will be performed following a successful installation.
  //
  //   clear_display
  //       turn off the text display.
  //
  //   enable_reboot
  //            packages can explicitly request that they want the user
  //            to be able to reboot during installation (useful for
  //            debugging packages that don't exit).
  //       packages can explicitly request that they want the user to be able to reboot during
  //       installation (useful for debugging packages that don't exit).
  //
  //   retry_update
  //            updater encounters some issue during the update. It requests
  //            a reboot to retry the same package automatically.
  //       updater encounters some issue during the update. It requests a reboot to retry the same
  //       package automatically.
  //
  //   log <string>
  //            updater requests logging the string (e.g. cause of the
  //            failure).
  //
  //   - the name of the package zip file.
  //
  //   - an optional argument "retry" if this update is a retry of a failed
  //   update attempt.
  //       updater requests logging the string (e.g. cause of the failure).
  //

  // Convert the std::string vector to a NULL-terminated char* vector suitable for execv.
  auto chr_args = StringVectorToNullTerminatedArray(args);
  std::vector<std::string> args;
  if (int update_status =
          is_ab ? SetUpAbUpdateCommands(package, zip, pipe_write.get(), &args)
                : SetUpNonAbUpdateCommands(package, zip, retry_count, pipe_write.get(), &args);
      update_status != 0) {
    log_buffer->push_back(android::base::StringPrintf("error: %d", kUpdateBinaryCommandFailure));
    return update_status;
  }

  pid_t pid = fork();

  if (pid == -1) {
    close(pipefd[0]);
    close(pipefd[1]);
    PLOG(ERROR) << "Failed to fork update binary";
    log_buffer->push_back(android::base::StringPrintf("error: %d", kForkUpdateBinaryFailure));
    return INSTALL_ERROR;
@@ -410,16 +396,18 @@ static int try_update_binary(const std::string& package, ZipArchiveHandle zip, b

  if (pid == 0) {
    umask(022);
    close(pipefd[0]);
    pipe_read.reset();

    // Convert the std::string vector to a NULL-terminated char* vector suitable for execv.
    auto chr_args = StringVectorToNullTerminatedArray(args);
    execv(chr_args[0], chr_args.data());
    // Bug: 34769056
    // We shouldn't use LOG/PLOG in the forked process, since they may cause
    // the child process to hang. This deadlock results from an improperly
    // copied mutex in the ui functions.
    // We shouldn't use LOG/PLOG in the forked process, since they may cause the child process to
    // hang. This deadlock results from an improperly copied mutex in the ui functions.
    // (Bug: 34769056)
    fprintf(stdout, "E:Can't run %s (%s)\n", chr_args[0], strerror(errno));
    _exit(EXIT_FAILURE);
  }
  close(pipefd[1]);
  pipe_write.reset();

  std::atomic<bool> logger_finished(false);
  std::thread temperature_logger(log_max_temperature, max_temperature, std::ref(logger_finished));
@@ -428,7 +416,7 @@ static int try_update_binary(const std::string& package, ZipArchiveHandle zip, b
  bool retry_update = false;

  char buffer[1024];
  FILE* from_child = fdopen(pipefd[0], "r");
  FILE* from_child = android::base::Fdopen(std::move(pipe_read), "r");
  while (fgets(buffer, sizeof(buffer), from_child) != nullptr) {
    std::string line(buffer);
    size_t space = line.find_first_of(" \n");
+12 −15
Original line number Diff line number Diff line
@@ -217,9 +217,10 @@ static void ListenRecoverySocket(RecoveryUI* ui, std::atomic<Device::BuiltinActi
}

static void redirect_stdio(const char* filename) {
  int pipefd[2];
  if (pipe(pipefd) == -1) {
    PLOG(ERROR) << "pipe failed";
  android::base::unique_fd pipe_read, pipe_write;
  // Create a pipe that allows parent process sending logs over.
  if (!android::base::Pipe(&pipe_read, &pipe_write)) {
    PLOG(ERROR) << "Failed to create pipe for redirecting stdio";

    // Fall back to traditional logging mode without timestamps. If these fail, there's not really
    // anywhere to complain...
@@ -233,7 +234,7 @@ static void redirect_stdio(const char* filename) {

  pid_t pid = fork();
  if (pid == -1) {
    PLOG(ERROR) << "fork failed";
    PLOG(ERROR) << "Failed to fork for redirecting stdio";

    // Fall back to traditional logging mode without timestamps. If these fail, there's not really
    // anywhere to complain...
@@ -246,8 +247,8 @@ static void redirect_stdio(const char* filename) {
  }

  if (pid == 0) {
    /// Close the unused write end.
    close(pipefd[1]);
    // Child process reads the incoming logs and doesn't write to the pipe.
    pipe_write.reset();

    auto start = std::chrono::steady_clock::now();

@@ -255,15 +256,13 @@ static void redirect_stdio(const char* filename) {
    FILE* log_fp = fopen(filename, "ae");
    if (log_fp == nullptr) {
      PLOG(ERROR) << "fopen \"" << filename << "\" failed";
      close(pipefd[0]);
      _exit(EXIT_FAILURE);
    }

    FILE* pipe_fp = fdopen(pipefd[0], "r");
    FILE* pipe_fp = android::base::Fdopen(std::move(pipe_read), "r");
    if (pipe_fp == nullptr) {
      PLOG(ERROR) << "fdopen failed";
      check_and_fclose(log_fp, filename);
      close(pipefd[0]);
      _exit(EXIT_FAILURE);
    }

@@ -283,25 +282,23 @@ static void redirect_stdio(const char* filename) {

    PLOG(ERROR) << "getline failed";

    fclose(pipe_fp);
    free(line);
    check_and_fclose(log_fp, filename);
    close(pipefd[0]);
    _exit(EXIT_FAILURE);
  } else {
    // Redirect stdout/stderr to the logger process. Close the unused read end.
    close(pipefd[0]);
    pipe_read.reset();

    setbuf(stdout, nullptr);
    setbuf(stderr, nullptr);

    if (dup2(pipefd[1], STDOUT_FILENO) == -1) {
    if (dup2(pipe_write.get(), STDOUT_FILENO) == -1) {
      PLOG(ERROR) << "dup2 stdout failed";
    }
    if (dup2(pipefd[1], STDERR_FILENO) == -1) {
    if (dup2(pipe_write.get(), STDERR_FILENO) == -1) {
      PLOG(ERROR) << "dup2 stderr failed";
    }

    close(pipefd[1]);
  }
}