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

Commit d7c894e0 authored by Kelvin Zhang's avatar Kelvin Zhang Committed by Automerger Merge Worker
Browse files

Merge "Do not call exit() immediately after serving sideload" am: a8e39494

Original change: https://android-review.googlesource.com/c/platform/bootable/recovery/+/1523478

MUST ONLY BE SUBMITTED BY AUTOMERGER

Change-Id: Ie1fa8397edbabb570cc276a5c26a72d88caf41bb
parents b1b27d11 a8e39494
Loading
Loading
Loading
Loading
+40 −1
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@
#include <string.h>
#include <unistd.h>

#include <chrono>
#include <functional>
#include <memory>
#include <set>
@@ -142,10 +143,48 @@ static MinadbdErrorCode RunAdbFuseSideload(int sfd, const std::string& args,
  return kMinadbdSuccess;
}

static bool WaitForSocketClose(int fd, std::chrono::milliseconds timeout) {
  const auto begin = std::chrono::steady_clock::now();
  const auto end = begin + timeout;
  while (std::chrono::steady_clock::now() < end) {
    // We don't care about reading the socket, we just want to wait until
    // socket closes. In this case .events = 0 will tell the kernel to wait
    // for close events.
    struct pollfd pfd = { .fd = fd, .events = 0 };
    auto timeout_ms = std::chrono::duration_cast<std::chrono::milliseconds>(
                          end - std::chrono::steady_clock::now())
                          .count();
    int rc = TEMP_FAILURE_RETRY(adb_poll(&pfd, 1, timeout_ms));
    if (rc == 1) {
      LOG(INFO) << "revents: " << pfd.revents;
      if (pfd.revents & (POLLHUP | POLLRDHUP)) {
        return true;
      }
    } else {
      PLOG(ERROR) << "poll() failed";
      // poll failed, almost definitely due to timeout
      // If not, you're screwed anyway, because it probably means the kernel ran
      // out of memory.
      return false;
    }
  }
  return false;
}

// Sideload service always exits after serving an install command.
static void SideloadHostService(unique_fd sfd, const std::string& args) {
  using namespace std::chrono_literals;
  MinadbdCommandStatus status;
  exit(RunAdbFuseSideload(sfd.get(), args, &status));
  auto error = RunAdbFuseSideload(sfd.get(), args, &status);
  // No need to wait if the socket is already closed, meaning the other end
  // already exited for some reason.
  if (error != kMinadbdHostSocketIOError) {
    // We sleep for a little bit just to wait for the host to receive last
    // "DONEDONE" message. However minadbd process is likely to get terminated
    // early due to exit_on_close
    WaitForSocketClose(sfd, 3000ms);
  }
  exit(error);
}

// Rescue service waits for the next command after an install command.