summaryrefslogtreecommitdiff
path: root/init/sigchld_handler.cpp
diff options
context:
space:
mode:
authorNikita Ioffe <ioffe@google.com>2019-10-09 15:23:02 +0100
committerNikita Ioffe <ioffe@google.com>2019-10-10 18:13:42 +0100
commit3f4b0d611338a772f63669bd12e792bbe43b1245 (patch)
treed8efb7ccefa34881d7e2ab2021a7702149f5babd /init/sigchld_handler.cpp
parentd11c6f7fd8ab1cd747d48b086a008f653b77ca3f (diff)
userspace reboot: stop post-data services and wait for them to be killed
* Refactored code around stopping services a little bit to reuse it between full reboot and userspace reboot. * Add a scope_guard to fallback to full reboot in case userspace reboot fails. * In case of userspace reboot init will also wait for services to be terminated/killed and log the ones that didn't react to SIGTERM/SIGKILL in time. * If some of the services didn't react to SIGKILL, fail userspace reboot. Test: adb reboot userspace Bug: 135984674 Change-Id: I820c7bc406169333b0f929f0eea028d8384eb2ac
Diffstat (limited to 'init/sigchld_handler.cpp')
-rw-r--r--init/sigchld_handler.cpp37
1 files changed, 30 insertions, 7 deletions
diff --git a/init/sigchld_handler.cpp b/init/sigchld_handler.cpp
index 984235de0..9b2c7d939 100644
--- a/init/sigchld_handler.cpp
+++ b/init/sigchld_handler.cpp
@@ -28,28 +28,31 @@
#include <android-base/scopeguard.h>
#include <android-base/stringprintf.h>
+#include <thread>
+
#include "init.h"
#include "service.h"
#include "service_list.h"
-using android::base::StringPrintf;
using android::base::boot_clock;
using android::base::make_scope_guard;
+using android::base::StringPrintf;
+using android::base::Timer;
namespace android {
namespace init {
-static bool ReapOneProcess() {
+static pid_t ReapOneProcess() {
siginfo_t siginfo = {};
// This returns a zombie pid or informs us that there are no zombies left to be reaped.
// It does NOT reap the pid; that is done below.
if (TEMP_FAILURE_RETRY(waitid(P_ALL, 0, &siginfo, WEXITED | WNOHANG | WNOWAIT)) != 0) {
PLOG(ERROR) << "waitid failed";
- return false;
+ return 0;
}
auto pid = siginfo.si_pid;
- if (pid == 0) return false;
+ if (pid == 0) return 0;
// At this point we know we have a zombie pid, so we use this scopeguard to reap the pid
// whenever the function returns from this point forward.
@@ -92,7 +95,7 @@ static bool ReapOneProcess() {
LOG(INFO) << name << " received signal " << siginfo.si_status << wait_string;
}
- if (!service) return true;
+ if (!service) return pid;
service->Reap(siginfo);
@@ -100,12 +103,32 @@ static bool ReapOneProcess() {
ServiceList::GetInstance().RemoveService(*service);
}
- return true;
+ return pid;
}
void ReapAnyOutstandingChildren() {
- while (ReapOneProcess()) {
+ while (ReapOneProcess() != 0) {
+ }
+}
+
+void WaitToBeReaped(const std::vector<pid_t>& pids, std::chrono::milliseconds timeout) {
+ Timer t;
+ std::vector<pid_t> alive_pids(pids.begin(), pids.end());
+ while (!alive_pids.empty() && t.duration() < timeout) {
+ pid_t pid;
+ while ((pid = ReapOneProcess()) != 0) {
+ auto it = std::find(alive_pids.begin(), alive_pids.end(), pid);
+ if (it != alive_pids.end()) {
+ alive_pids.erase(it);
+ }
+ }
+ if (alive_pids.empty()) {
+ break;
+ }
+ std::this_thread::sleep_for(50ms);
}
+ LOG(INFO) << "Waiting for " << pids.size() << " pids to be reaped took " << t << " with "
+ << alive_pids.size() << " of them still running";
}
} // namespace init