diff options
Diffstat (limited to 'init/sigchld_handler.cpp')
-rw-r--r-- | init/sigchld_handler.cpp | 37 |
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 |