chiark / gitweb /
units: rename [Meta] section to [Unit]
[elogind.git] / main.c
diff --git a/main.c b/main.c
index 622ba631519b90811d92e8aae79d9c15acf5514f..c473ced2b41c04e0e2bd01e1424423ddd0e6c582 100644 (file)
--- 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,21 +119,28 @@ _noreturn static void crash(int sig) {
                 chvt(crash_chvt);
 
         if (crash_shell) {
-                sigset_t mask;
+                struct sigaction sa;
+                pid_t pid;
 
                 log_info("Executing crash shell in 10s...");
                 sleep(10);
 
-                /* Make sure the signal is not delivered inside the
-                 * exec() */
-                assert_se(sigemptyset(&mask) == 0);
-                assert_se(sigaddset(&mask, sig) == 0);
-                assert_se(sigprocmask(SIG_SETMASK, &mask, NULL) == 0);
+                /* 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);
 
-                ignore_signal(sig);
+                        log_error("execl() failed: %s", strerror(errno));
+                        _exit(1);
+                }
 
-                execl("/bin/sh", "/bin/sh", NULL);
-                log_error("execl() failed: %s", strerror(errno));
+                log_info("Successfully spawned crash shall as pid %llu.", (unsigned long long) pid);
         }
 
         log_info("Freezing execution.");
@@ -250,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;
 
@@ -269,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;
@@ -529,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;
                 }