Do not call exit() immediately after serving sideload
Wait for socket to close before exit(), so that last "DONEDONE" message is correctly sent. Test: enter recovery, sideload an OTA, verify that no read error occured on client side. Repeat 5 times. Bug: 155158483 Change-Id: Ibb02548d8c03fb77f8f60cb69cff84c33903adc0
This commit is contained in:
parent
b1b27d1113
commit
e32c9f728e
1 changed files with 40 additions and 1 deletions
|
@ -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.
|
||||
|
|
Loading…
Reference in a new issue