init: Handle SIGCHLD signals
This commit is contained in:
parent
5f0830cd41
commit
81131ad3a8
102
apps/init.cpp
102
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<int> sysinit(StringView path)
|
||||
{
|
||||
if (getpid() != 1)
|
||||
@ -404,38 +438,7 @@ Result<int> 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<int> user_init(StringView path)
|
||||
@ -454,38 +457,7 @@ Result<int> 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<int> luna_main(int argc, char** argv)
|
||||
@ -501,6 +473,8 @@ Result<int> 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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user