X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=main.c;h=c473ced2b41c04e0e2bd01e1424423ddd0e6c582;hb=6dde1f33e1249a8a6b354372dd95065f26b8c712;hp=3e2bfe10ca94b5ed384a9e6ca205d848c5de8e08;hpb=a337c6fcee2ab43bf791968f265a0a937715a3ff;p=elogind.git diff --git a/main.c b/main.c index 3e2bfe10c..c473ced2b 100644 --- a/main.c +++ b/main.c @@ -59,18 +59,27 @@ _noreturn static void freeze(void) { pause(); } +static void nop_handler(int sig) { +} + _noreturn static void crash(int sig) { if (!dump_core) log_error("Caught <%s>, not dumping core.", strsignal(sig)); else { + struct sigaction sa; pid_t pid; + /* We want to wait for the core process, hence let's enable SIGCHLD */ + zero(sa); + sa.sa_handler = nop_handler; + sa.sa_flags = SA_NOCLDSTOP|SA_RESTART; + assert_se(sigaction(SIGCHLD, &sa, NULL) == 0); + if ((pid = fork()) < 0) log_error("Caught <%s>, cannot fork for core dump: %s", strsignal(sig), strerror(errno)); else if (pid == 0) { - struct sigaction sa; struct rlimit rl; /* Enable default signal handler for core dump */ @@ -110,11 +119,28 @@ _noreturn static void crash(int sig) { chvt(crash_chvt); if (crash_shell) { + struct sigaction sa; + pid_t pid; + log_info("Executing crash shell in 10s..."); sleep(10); - execl("/bin/sh", "/bin/sh", NULL); - log_error("execl() failed: %s", strerror(errno)); + /* Let the kernel reap children for us */ + zero(sa); + sa.sa_handler = SIG_IGN; + sa.sa_flags = SA_NOCLDSTOP|SA_NOCLDWAIT|SA_RESTART; + assert_se(sigaction(SIGCHLD, &sa, NULL) == 0); + + if ((pid = fork()) < 0) + log_error("Failed to fork off crash shell: %s", strerror(errno)); + else if (pid == 0) { + execl("/bin/sh", "/bin/sh", NULL); + + log_error("execl() failed: %s", strerror(errno)); + _exit(1); + } + + log_info("Successfully spawned crash shall as pid %llu.", (unsigned long long) pid); } log_info("Freezing execution."); @@ -240,6 +266,15 @@ static int parse_proc_cmdline_word(const char *word) { else crash_shell = r; + + } else if (startswith(word, "systemd.confirm_spawn=")) { + int r; + + if ((r = parse_boolean(word + 22)) < 0) + log_warning("Failed to parse confirm spawn switch %s, Ignoring.", word + 22); + else + confirm_spawn = r; + } else if (startswith(word, "systemd.crash_chvt=")) { int k; @@ -259,6 +294,7 @@ static int parse_proc_cmdline_word(const char *word) { log_info("systemd.dump_core=0|1 Dump core on crash"); log_info("systemd.crash_shell=0|1 On crash run shell"); log_info("systemd.crash_chvt=N Change to VT #N on crash"); + log_info("systemd.confirm_spawn=0|1 Confirm every process spawn"); } else { unsigned i; @@ -519,11 +555,11 @@ int main(int argc, char *argv[]) { log_debug("Activating default unit: %s", default_unit); - if ((r = manager_load_unit(m, default_unit, &target)) < 0) { + if ((r = manager_load_unit(m, default_unit, NULL, &target)) < 0) { log_error("Failed to load default target: %s", strerror(-r)); log_info("Trying to load rescue target..."); - if ((r = manager_load_unit(m, SPECIAL_RESCUE_TARGET, &target)) < 0) { + if ((r = manager_load_unit(m, SPECIAL_RESCUE_TARGET, NULL, &target)) < 0) { log_error("Failed to load rescue target: %s", strerror(-r)); goto finish; } @@ -567,5 +603,8 @@ finish: dbus_shutdown(); + if (getpid() == 1) + freeze(); + return retval; }