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 */
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);
- execl("/bin/sh", "/bin/sh", NULL);
- log_error("execl() failed: %s", strerror(errno));
+ 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.");
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;
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;
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;
}
dbus_shutdown();
+ if (getpid() == 1)
+ freeze();
+
return retval;
}