summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKelvin Zhang <zhangkelvin@google.com>2020-12-15 20:28:47 +0100
committerAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>2020-12-15 20:28:47 +0100
commitd7901f47588e561e50b14dcbd5e16b1b195a946f (patch)
tree3447410ffd246824671ed14008335375d1b2a255
parent[automerger skipped] Import translations. DO NOT MERGE ANYWHERE am: b1b27d1113 -s ours am: 0919091d63 -s ours (diff)
parentMerge "Do not call exit() immediately after serving sideload" am: a8e394942e am: d7c894e0bc (diff)
downloadandroid_bootable_recovery-d7901f47588e561e50b14dcbd5e16b1b195a946f.tar
android_bootable_recovery-d7901f47588e561e50b14dcbd5e16b1b195a946f.tar.gz
android_bootable_recovery-d7901f47588e561e50b14dcbd5e16b1b195a946f.tar.bz2
android_bootable_recovery-d7901f47588e561e50b14dcbd5e16b1b195a946f.tar.lz
android_bootable_recovery-d7901f47588e561e50b14dcbd5e16b1b195a946f.tar.xz
android_bootable_recovery-d7901f47588e561e50b14dcbd5e16b1b195a946f.tar.zst
android_bootable_recovery-d7901f47588e561e50b14dcbd5e16b1b195a946f.zip
-rw-r--r--minadbd/minadbd_services.cpp41
1 files changed, 40 insertions, 1 deletions
diff --git a/minadbd/minadbd_services.cpp b/minadbd/minadbd_services.cpp
index ff91ba931..0abe8675b 100644
--- a/minadbd/minadbd_services.cpp
+++ b/minadbd/minadbd_services.cpp
@@ -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.