diff --git a/init/init.cpp b/init/init.cpp index c965fe635..05a8a9cc5 100644 --- a/init/init.cpp +++ b/init/init.cpp @@ -1109,8 +1109,11 @@ int SecondStageMain(int argc, char** argv) { // Restore prio before main loop setpriority(PRIO_PROCESS, 0, 0); while (true) { - // By default, sleep until something happens. - std::optional epoll_timeout; + // By default, sleep until something happens. Do not convert far_future into + // std::chrono::milliseconds because that would trigger an overflow. The unit of boot_clock + // is 1ns. + const boot_clock::time_point far_future = boot_clock::time_point::max(); + boot_clock::time_point next_action_time = far_future; auto shutdown_command = shutdown_state.CheckShutdown(); if (shutdown_command) { @@ -1122,23 +1125,28 @@ int SecondStageMain(int argc, char** argv) { if (!(prop_waiter_state.MightBeWaiting() || Service::is_exec_service_running())) { am.ExecuteOneCommand(); + // If there's more work to do, wake up again immediately. + if (am.HasMoreCommands()) { + next_action_time = boot_clock::now(); + } } + // Since the above code examined pending actions, no new actions must be + // queued by the code between this line and the Epoll::Wait() call below + // without calling WakeMainInitThread(). if (!IsShuttingDown()) { auto next_process_action_time = HandleProcessActions(); // If there's a process that needs restarting, wake up in time for that. if (next_process_action_time) { - epoll_timeout = std::chrono::ceil( - *next_process_action_time - boot_clock::now()); - if (epoll_timeout < 0ms) epoll_timeout = 0ms; + next_action_time = std::min(next_action_time, *next_process_action_time); } } - if (!(prop_waiter_state.MightBeWaiting() || Service::is_exec_service_running())) { - // If there's more work to do, wake up again immediately. - if (am.HasMoreCommands()) epoll_timeout = 0ms; + std::optional epoll_timeout; + if (next_action_time != far_future) { + epoll_timeout = std::chrono::ceil( + std::max(next_action_time - boot_clock::now(), 0ns)); } - auto epoll_result = epoll.Wait(epoll_timeout); if (!epoll_result.ok()) { LOG(ERROR) << epoll_result.error();