init: Make WaitToBeReaped() wait less long
Reduce the time spent in WaitToBeReaped() by waiting for SIGCHLD instead
of waiting for 50 ms.
Bug: 308687042
Change-Id: I5e259fdd22dec68e45d27205def2fc6463c06ca3
Signed-off-by: Bart Van Assche <bvanassche@google.com>
diff --git a/init/sigchld_handler.cpp b/init/sigchld_handler.cpp
index 0901a96..9d4c7c8 100644
--- a/init/sigchld_handler.cpp
+++ b/init/sigchld_handler.cpp
@@ -18,6 +18,7 @@
#include <signal.h>
#include <string.h>
+#include <sys/signalfd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/wait.h>
@@ -31,6 +32,7 @@
#include <thread>
+#include "epoll.h"
#include "init.h"
#include "service.h"
#include "service_list.h"
@@ -121,8 +123,23 @@
}
}
-void WaitToBeReaped(const std::vector<pid_t>& pids, std::chrono::milliseconds timeout) {
+static void DiscardSiginfo(int signal_fd) {
+ signalfd_siginfo siginfo;
+ ssize_t bytes_read = TEMP_FAILURE_RETRY(read(signal_fd, &siginfo, sizeof(siginfo)));
+ if (bytes_read != sizeof(siginfo)) {
+ LOG(WARNING) << "Unexpected: " << __func__ << " read " << bytes_read << " bytes instead of "
+ << sizeof(siginfo);
+ }
+}
+
+void WaitToBeReaped(int sigchld_fd, const std::vector<pid_t>& 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<pid_t> alive_pids(pids.begin(), pids.end());
while (!alive_pids.empty() && t.duration() < timeout) {
pid_t pid;
@@ -135,7 +152,11 @@
if (alive_pids.empty()) {
break;
}
- std::this_thread::sleep_for(50ms);
+ if (sigchld_fd >= 0) {
+ epoll.Wait(std::max(timeout - t.duration(), 0ms));
+ } else {
+ 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";