libsnapshot: Wait for daemon to terminate after snapshot unamp

During verification, update-engine will invoke
SnapshotMap() and Unmap() for every partition verification.

Post Unmap(), update-engine immediately invokes Map()
for next partition. This is a narrow window wherein, daemon
from previous unmap() is still present and init hasn't
terminated it. Thus, when next MapSnapshot() is invoked,
Connect() fails as init may end up terminating the service.

Wait for the daemon to fully terminate and exit
when Detach() is invoked.

Bug: 258514587
Test: OTA on Pixel, Map/Unmap in a loop
Change-Id: I36b7ce183dfa4c89a873118876d195480e28d48c
Signed-off-by: Akilesh Kailash <akailash@google.com>
This commit is contained in:
Akilesh Kailash 2023-02-10 14:26:10 -08:00
parent 9ed4eb61a6
commit d2063ad7dd
2 changed files with 19 additions and 0 deletions

View file

@ -47,6 +47,8 @@ class SnapuserdClient {
bool ValidateConnection();
std::string GetDaemonAliveIndicatorPath();
void WaitForServiceToTerminate(std::chrono::milliseconds timeout_ms);
public:
explicit SnapuserdClient(android::base::unique_fd&& sockfd);
SnapuserdClient(){};

View file

@ -94,6 +94,21 @@ std::unique_ptr<SnapuserdClient> SnapuserdClient::Connect(const std::string& soc
return client;
}
void SnapuserdClient::WaitForServiceToTerminate(std::chrono::milliseconds timeout_ms) {
auto start = std::chrono::steady_clock::now();
while (android::base::GetProperty("init.svc.snapuserd", "") == "running") {
auto now = std::chrono::steady_clock::now();
auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(now - start);
if (elapsed >= timeout_ms) {
LOG(ERROR) << "Timed out - Snapuserd service did not stop - Forcefully terminating the "
"service";
android::base::SetProperty("ctl.stop", "snapuserd");
return;
}
std::this_thread::sleep_for(100ms);
}
}
bool SnapuserdClient::ValidateConnection() {
if (!Sendmsg("query")) {
return false;
@ -238,6 +253,8 @@ bool SnapuserdClient::DetachSnapuserd() {
LOG(ERROR) << "Failed to detach snapuserd.";
return false;
}
WaitForServiceToTerminate(3s);
return true;
}