diff options
author | Tom Cherry <tomcherry@google.com> | 2017-07-28 15:22:23 -0700 |
---|---|---|
committer | Tom Cherry <tomcherry@google.com> | 2017-08-01 11:06:17 -0700 |
commit | eeee83106bfbd719b52817c2ebb460ce38bcc494 (patch) | |
tree | 013d9a9b84965237f67d43a732027413e8918053 /init/signal_handler.cpp | |
parent | 3b81f2d623c6cba45ad07fa91338d346d9b96482 (diff) |
init: move reaping from ServiceManager to signal_handler.cpp
signal_handler.cpp itself needs to be cleaned up, but this is a step
to clean up ServiceManager.
Test: boot bullhead
Change-Id: I81f1e8ac4d09692cfb364bc702cbd3deb61aa55a
Diffstat (limited to 'init/signal_handler.cpp')
-rw-r--r-- | init/signal_handler.cpp | 74 |
1 files changed, 72 insertions, 2 deletions
diff --git a/init/signal_handler.cpp b/init/signal_handler.cpp index db1bfcf8c..d77a2123b 100644 --- a/init/signal_handler.cpp +++ b/init/signal_handler.cpp @@ -14,29 +14,94 @@ * limitations under the License. */ +#include "signal_handler.h" + #include <signal.h> #include <string.h> #include <sys/socket.h> #include <sys/types.h> +#include <sys/wait.h> #include <unistd.h> +#include <android-base/chrono_utils.h> #include <android-base/logging.h> +#include <android-base/scopeguard.h> +#include <android-base/stringprintf.h> #include "init.h" +#include "property_service.h" #include "service.h" +using android::base::StringPrintf; +using android::base::boot_clock; +using android::base::make_scope_guard; + namespace android { namespace init { static int signal_write_fd = -1; static int signal_read_fd = -1; +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)); }); + + if (PropertyChildReap(pid)) return true; + + Service* service = ServiceManager::GetInstance().FindServiceByPid(pid); + + std::string name; + std::string wait_string; + 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) { + ServiceManager::GetInstance().RemoveService(*service); + } + + return true; +} + static void handle_signal() { // Clear outstanding requests. char buf[32]; read(signal_read_fd, buf, sizeof(buf)); - ServiceManager::GetInstance().ReapAnyOutstandingChildren(); + ReapAnyOutstandingChildren(); } static void SIGCHLD_handler(int) { @@ -45,6 +110,11 @@ static void SIGCHLD_handler(int) { } } +void ReapAnyOutstandingChildren() { + while (ReapOneProcess()) { + } +} + void signal_handler_init() { // Create a signalling mechanism for SIGCHLD. int s[2]; @@ -63,7 +133,7 @@ void signal_handler_init() { act.sa_flags = SA_NOCLDSTOP; sigaction(SIGCHLD, &act, 0); - ServiceManager::GetInstance().ReapAnyOutstandingChildren(); + ReapAnyOutstandingChildren(); register_epoll_handler(signal_read_fd, handle_signal); } |