static bool 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; } auto pid = siginfo.si_pid; if (pid == 0) return false; // 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. // We do NOT want to reap the zombie earlier as in Service::Reap(), we kill(-pid, ...) and we // want the pid to remain valid throughout that (and potentially future) usages. auto reaper = make_scope_guard([pid] { TEMP_FAILURE_RETRY(waitpid(pid, nullptr, WNOHANG)); }); std::string name; std::string wait_string; Service* service = nullptr; if (PropertyChildReap(pid)) { name = "Async property child"; } else if (SubcontextChildReap(pid)) { name = "Subcontext"; } else { service = ServiceList::GetInstance().FindService(pid, &Service::pid); if (service) { name = StringPrintf("Service '%s' (pid %d)", service->name().c_str(), pid); if (service->flags() & SVC_EXEC) { auto exec_duration = boot_clock::now() - service->time_started(); auto exec_duration_ms = std::chrono::duration_cast<std::chrono::milliseconds>(exec_duration).count(); wait_string = StringPrintf(" waiting took %f seconds", exec_duration_ms / 1000.0f); } } else { name = StringPrintf("Untracked pid %d", pid); } } auto status = siginfo.si_status; if (WIFEXITED(status)) { LOG(INFO) << name << " exited with status " << WEXITSTATUS(status) << wait_string; } else if (WIFSIGNALED(status)) { LOG(INFO) << name << " killed by signal " << WTERMSIG(status) << wait_string; } if (!service) return true; service->Reap(); if (service->flags() & SVC_TEMPORARY) { ServiceList::GetInstance().RemoveService(*service); } return true; }
bool ServiceManager::ReapOneProcess() { int status; pid_t pid = TEMP_FAILURE_RETRY(waitpid(-1, &status, WNOHANG)); if (pid == 0) { return false; } else if (pid == -1) { PLOG(ERROR) << "waitpid failed"; return false; } Service* svc = FindServiceByPid(pid); std::string name; if (svc) { name = android::base::StringPrintf("Service '%s' (pid %d)", svc->name().c_str(), pid); } else { name = android::base::StringPrintf("Untracked pid %d", pid); } if (WIFEXITED(status)) { LOG(VERBOSE) << name << " exited with status " << WEXITSTATUS(status); } else if (WIFSIGNALED(status)) { LOG(VERBOSE) << name << " killed by signal " << WTERMSIG(status); } else if (WIFSTOPPED(status)) { LOG(VERBOSE) << name << " stopped by signal " << WSTOPSIG(status); } else { LOG(VERBOSE) << name << " state changed"; } if (!svc) { return true; } if (svc->Reap()) { waiting_for_exec = false; RemoveService(*svc); } return true; }
bool ServiceManager::ReapOneProcess() { int status; pid_t pid = TEMP_FAILURE_RETRY(waitpid(-1, &status, WNOHANG)); if (pid == 0) { return false; } else if (pid == -1) { ERROR("waitpid failed: %s\n", strerror(errno)); return false; } Service* svc = FindServiceByPid(pid); std::string name; if (svc) { name = android::base::StringPrintf("Service '%s' (pid %d)", svc->name().c_str(), pid); } else { name = android::base::StringPrintf("Untracked pid %d", pid); } if (WIFEXITED(status)) { NOTICE("%s exited with status %d\n", name.c_str(), WEXITSTATUS(status)); } else if (WIFSIGNALED(status)) { NOTICE("%s killed by signal %d\n", name.c_str(), WTERMSIG(status)); } else if (WIFSTOPPED(status)) { NOTICE("%s stopped by signal %d\n", name.c_str(), WSTOPSIG(status)); } else { NOTICE("%s state changed", name.c_str()); } if (!svc) { return true; } if (svc->Reap()) { waiting_for_exec = false; RemoveService(*svc); } return true; }