diff --git a/apps/init.cpp b/apps/init.cpp index b0c2c7d9..07637ad2 100644 --- a/apps/init.cpp +++ b/apps/init.cpp @@ -365,6 +365,40 @@ static void mount_devpts() if (mount("/dev/pts", "devpts", "devpts") < 0) exit(255); } +static void wait_for_child(int) +{ + int status; + auto rc = os::Process::wait(os::Process::ANY_CHILD, &status); + if (rc.has_error()) + { + do_log("[init] waitpid error %s", rc.error_string()); + return; + } + + pid_t child = rc.release_value(); + + for (auto& service : g_services) + { + if (service.pid.has_value() && service.pid.value() == child) + { + if (WIFEXITED(status)) + { + do_log("[init] service %s exited with status %d\n", service.name.chars(), WEXITSTATUS(status)); + } + else { do_log("[init] service %s was terminated by signal %d\n", service.name.chars(), WTERMSIG(status)); } + + if (service.restart) + { + do_log("[init] restarting service %s\n", service.name.chars()); + + start_service(service); + } + + break; + } + } +} + Result sysinit(StringView path) { if (getpid() != 1) @@ -404,38 +438,7 @@ Result sysinit(StringView path) if (path.is_empty()) path = "/etc/init"; start_services(path); - while (1) - { - int status; - auto rc = os::Process::wait(os::Process::ANY_CHILD, &status); - if (rc.has_error()) continue; - - pid_t child = rc.release_value(); - - for (auto& service : g_services) - { - if (service.pid.has_value() && service.pid.value() == child) - { - if (WIFEXITED(status)) - { - do_log("[init] service %s exited with status %d\n", service.name.chars(), WEXITSTATUS(status)); - } - else - { - do_log("[init] service %s was terminated by signal %d\n", service.name.chars(), WTERMSIG(status)); - } - - if (service.restart) - { - do_log("[init] restarting service %s\n", service.name.chars()); - - start_service(service); - } - - break; - } - } - } + while (1) { wait_for_child(0); } } Result user_init(StringView path) @@ -454,38 +457,7 @@ Result user_init(StringView path) TRY(os::Security::pledge("stdio rpath wpath proc exec", nullptr)); - while (1) - { - int status; - auto rc = os::Process::wait(os::Process::ANY_CHILD, &status); - if (rc.has_error()) continue; - - pid_t child = rc.release_value(); - - for (auto& service : g_services) - { - if (service.pid.has_value() && service.pid.value() == child) - { - if (WIFEXITED(status)) - { - do_log("[init] service %s exited with status %d\n", service.name.chars(), WEXITSTATUS(status)); - } - else - { - do_log("[init] service %s was terminated by signal %d\n", service.name.chars(), WTERMSIG(status)); - } - - if (service.restart) - { - do_log("[init] restarting service %s\n", service.name.chars()); - - start_service(service); - } - - break; - } - } - } + while (1) { wait_for_child(0); } } Result luna_main(int argc, char** argv) @@ -501,6 +473,8 @@ Result luna_main(int argc, char** argv) "change the default service path (/etc/init or /etc/user)"); parser.parse(argc, argv); + signal(SIGCHLD, wait_for_child); + if (user) return user_init(service_path); return sysinit(service_path); }