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 <bvanassche@google.com>
diff --git a/init/sigchld_handler.cpp b/init/sigchld_handler.cpp
index 0279508..8e9e713 100644
--- a/init/sigchld_handler.cpp
+++ b/init/sigchld_handler.cpp
@@ -138,7 +138,7 @@
     }
 }
 
-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 @@
                     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) {
-        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<pid_t> 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) {