diff --git a/init/epoll.cpp b/init/epoll.cpp index 01d886717..17d63fa5d 100644 --- a/init/epoll.cpp +++ b/init/epoll.cpp @@ -69,19 +69,24 @@ Result Epoll::UnregisterHandler(int fd) { return {}; } -Result Epoll::Wait(std::optional timeout) { +Result*>> Epoll::Wait( + std::optional 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*>(ev.data.ptr)); } - return {}; + std::vector*> pending_functions; + for (int i = 0; i < num_events; ++i) { + pending_functions.emplace_back(reinterpret_cast*>(ev[i].data.ptr)); + } + + return pending_functions; } } // namespace init diff --git a/init/epoll.h b/init/epoll.h index ca8426634..c32a6614f 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 #include @@ -24,6 +23,7 @@ #include #include #include +#include #include @@ -39,7 +39,8 @@ class Epoll { Result Open(); Result RegisterHandler(int fd, std::function handler, uint32_t events = EPOLLIN); Result UnregisterHandler(int fd); - Result Wait(std::optional timeout); + Result*>> Wait( + std::optional timeout); private: android::base::unique_fd epoll_fd_; @@ -48,5 +49,3 @@ class Epoll { } // namespace init } // namespace android - -#endif diff --git a/init/init.cpp b/init/init.cpp index ce898dee0..d4cbb5f57 100644 --- a/init/init.cpp +++ b/init/init.cpp @@ -787,8 +787,17 @@ int SecondStageMain(int argc, char** argv) { 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 33373d473..6e9b337a2 100644 --- a/init/keychords_test.cpp +++ b/init/keychords_test.cpp @@ -212,7 +212,11 @@ TestFrame::TestFrame(const std::vector>& chords, EventHan } 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) {