From 1daf88d6ceb1530c36f30dad49628434b2bc7b4d Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Thu, 16 Nov 2023 11:19:08 -0800 Subject: [PATCH] init: Fix signalfd support in WaitToBeReaped() Add an Epoll::Open() call such that the Epoll::Wait() calls wait for the signalfd. Rename DiscardSiginfo() into HandleSignal(). Handle Epoll method call failures. Test whether alive_pids is empty once per loop iteration. Test: CtsInitTestCases:ServiceStopTest Change-Id: I16c27aa74d61f889b304f3e59cd3c5255c299ce1 Signed-off-by: Bart Van Assche --- init/sigchld_handler.cpp | 41 +++++++++++++++++++++++++++------------- 1 file changed, 28 insertions(+), 13 deletions(-) diff --git a/init/sigchld_handler.cpp b/init/sigchld_handler.cpp index 02795080a..8e9e713c4 100644 --- a/init/sigchld_handler.cpp +++ b/init/sigchld_handler.cpp @@ -138,7 +138,7 @@ static void ReapAndRemove(std::vector& alive_pids) { } } -static void DiscardSiginfo(int signal_fd) { +static void HandleSignal(int signal_fd) { signalfd_siginfo siginfo; ssize_t bytes_read = TEMP_FAILURE_RETRY(read(signal_fd, &siginfo, sizeof(siginfo))); if (bytes_read != sizeof(siginfo)) { @@ -151,22 +151,37 @@ void WaitToBeReaped(int sigchld_fd, const std::vector& pids, std::chrono::milliseconds timeout) { Timer t; Epoll epoll; - // The init process passes a valid sigchld_fd argument but unit tests do not. if (sigchld_fd >= 0) { - epoll.RegisterHandler(sigchld_fd, [sigchld_fd]() { DiscardSiginfo(sigchld_fd); }); - } - std::vector alive_pids(pids.begin(), pids.end()); - while (!alive_pids.empty() && t.duration() < timeout) { - ReapAndRemove(alive_pids); - if (alive_pids.empty()) { - break; - } - if (sigchld_fd >= 0) { - epoll.Wait(std::max(timeout - t.duration(), 0ms)); + if (auto result = epoll.Open(); result.ok()) { + result = + epoll.RegisterHandler(sigchld_fd, [sigchld_fd]() { HandleSignal(sigchld_fd); }); + if (!result.ok()) { + LOG(WARNING) << __func__ + << " RegisterHandler() failed. Falling back to sleep_for(): " + << result.error(); + sigchld_fd = -1; + } } else { - std::this_thread::sleep_for(50ms); + LOG(WARNING) << __func__ << " Epoll::Open() failed. Falling back to sleep_for(): " + << result.error(); + sigchld_fd = -1; } } + std::vector alive_pids(pids); + ReapAndRemove(alive_pids); + while (!alive_pids.empty() && t.duration() < timeout) { + if (sigchld_fd >= 0) { + auto result = epoll.Wait(std::max(timeout - t.duration(), 0ms)); + if (result.ok()) { + ReapAndRemove(alive_pids); + continue; + } else { + LOG(WARNING) << "Epoll::Wait() failed " << result.error(); + } + } + std::this_thread::sleep_for(50ms); + ReapAndRemove(alive_pids); + } LOG(INFO) << "Waiting for " << pids.size() << " pids to be reaped took " << t << " with " << alive_pids.size() << " of them still running"; for (pid_t pid : alive_pids) {