Merge "init: Always reap processes before handling properties"
am: 0589aa4265

Change-Id: I825598315caa2a6fe592f293815adf8242f0a644
diff --git a/init/epoll.cpp b/init/epoll.cpp
index 01d8867..17d63fa 100644
--- a/init/epoll.cpp
+++ b/init/epoll.cpp
@@ -69,19 +69,24 @@
     return {};
 }
 
-Result<void> Epoll::Wait(std::optional<std::chrono::milliseconds> timeout) {
+Result<std::vector<std::function<void()>*>> Epoll::Wait(
+        std::optional<std::chrono::milliseconds> timeout) {
     int timeout_ms = -1;
     if (timeout && timeout->count() < INT_MAX) {
         timeout_ms = timeout->count();
     }
-    epoll_event ev;
-    auto nr = TEMP_FAILURE_RETRY(epoll_wait(epoll_fd_, &ev, 1, timeout_ms));
-    if (nr == -1) {
+    const auto max_events = epoll_handlers_.size();
+    epoll_event ev[max_events];
+    auto num_events = TEMP_FAILURE_RETRY(epoll_wait(epoll_fd_, ev, max_events, timeout_ms));
+    if (num_events == -1) {
         return ErrnoError() << "epoll_wait failed";
-    } else if (nr == 1) {
-        std::invoke(*reinterpret_cast<std::function<void()>*>(ev.data.ptr));
     }
-    return {};
+    std::vector<std::function<void()>*> pending_functions;
+    for (int i = 0; i < num_events; ++i) {
+        pending_functions.emplace_back(reinterpret_cast<std::function<void()>*>(ev[i].data.ptr));
+    }
+
+    return pending_functions;
 }
 
 }  // namespace init
diff --git a/init/epoll.h b/init/epoll.h
index ca84266..c32a661 100644
--- a/init/epoll.h
+++ b/init/epoll.h
@@ -14,8 +14,7 @@
  * limitations under the License.
  */
 
-#ifndef _INIT_EPOLL_H
-#define _INIT_EPOLL_H
+#pragma once
 
 #include <stdint.h>
 #include <sys/epoll.h>
@@ -24,6 +23,7 @@
 #include <functional>
 #include <map>
 #include <optional>
+#include <vector>
 
 #include <android-base/unique_fd.h>
 
@@ -39,7 +39,8 @@
     Result<void> Open();
     Result<void> RegisterHandler(int fd, std::function<void()> handler, uint32_t events = EPOLLIN);
     Result<void> UnregisterHandler(int fd);
-    Result<void> Wait(std::optional<std::chrono::milliseconds> timeout);
+    Result<std::vector<std::function<void()>*>> Wait(
+            std::optional<std::chrono::milliseconds> timeout);
 
   private:
     android::base::unique_fd epoll_fd_;
@@ -48,5 +49,3 @@
 
 }  // namespace init
 }  // namespace android
-
-#endif
diff --git a/init/init.cpp b/init/init.cpp
index ce898de..d4cbb5f 100644
--- a/init/init.cpp
+++ b/init/init.cpp
@@ -787,8 +787,17 @@
             if (am.HasMoreCommands()) epoll_timeout = 0ms;
         }
 
-        if (auto result = epoll.Wait(epoll_timeout); !result) {
-            LOG(ERROR) << result.error();
+        auto pending_functions = epoll.Wait(epoll_timeout);
+        if (!pending_functions) {
+            LOG(ERROR) << pending_functions.error();
+        } else if (!pending_functions->empty()) {
+            // We always reap children before responding to the other pending functions. This is to
+            // prevent a race where other daemons see that a service has exited and ask init to
+            // start it again via ctl.start before init has reaped it.
+            ReapAnyOutstandingChildren();
+            for (const auto& function : *pending_functions) {
+                (*function)();
+            }
         }
     }
 
diff --git a/init/keychords_test.cpp b/init/keychords_test.cpp
index 33373d4..6e9b337 100644
--- a/init/keychords_test.cpp
+++ b/init/keychords_test.cpp
@@ -212,7 +212,11 @@
 }
 
 void TestFrame::RelaxForMs(std::chrono::milliseconds wait) {
-    epoll_.Wait(wait);
+    auto pending_functions = epoll_.Wait(wait);
+    ASSERT_TRUE(pending_functions) << pending_functions.error();
+    for (const auto& function : *pending_functions) {
+        (*function)();
+    }
 }
 
 void TestFrame::SetChord(int key, bool value) {