diff --git a/init/epoll.cpp b/init/epoll.cpp index 0580f8608..24d356da1 100644 --- a/init/epoll.cpp +++ b/init/epoll.cpp @@ -75,6 +75,10 @@ Result Epoll::UnregisterHandler(int fd) { return {}; } +void Epoll::SetFirstCallback(std::function first_callback) { + first_callback_ = std::move(first_callback); +} + Result>> Epoll::Wait( std::optional timeout) { int timeout_ms = -1; @@ -87,6 +91,9 @@ Result>> Epoll::Wait( if (num_events == -1) { return ErrnoError() << "epoll_wait failed"; } + if (num_events > 0 && first_callback_) { + first_callback_(); + } std::vector> pending_functions; for (int i = 0; i < num_events; ++i) { auto& info = *reinterpret_cast(ev[i].data.ptr); diff --git a/init/epoll.h b/init/epoll.h index f58ae8df3..e26e31936 100644 --- a/init/epoll.h +++ b/init/epoll.h @@ -42,6 +42,7 @@ class Epoll { Result Open(); Result RegisterHandler(int fd, Handler handler, uint32_t events = EPOLLIN); Result UnregisterHandler(int fd); + void SetFirstCallback(std::function first_callback); Result>> Wait( std::optional timeout); @@ -53,6 +54,7 @@ class Epoll { android::base::unique_fd epoll_fd_; std::map epoll_handlers_; + std::function first_callback_; }; } // namespace init diff --git a/init/init.cpp b/init/init.cpp index ce668d7d3..cd0ee58ec 100644 --- a/init/init.cpp +++ b/init/init.cpp @@ -1061,6 +1061,11 @@ int SecondStageMain(int argc, char** argv) { PLOG(FATAL) << result.error(); } + // 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. + epoll.SetFirstCallback(ReapAnyOutstandingChildren); + InstallSignalFdHandler(&epoll); InstallInitNotifier(&epoll); StartPropertyService(&property_fd); @@ -1176,10 +1181,6 @@ int SecondStageMain(int argc, char** argv) { if (!pending_functions.ok()) { 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)(); }