#include <sys/stat.h>
#include <getopt.h>
#include <signal.h>
+#include <sys/wait.h>
#include "manager.h"
#include "log.h"
static char *default_unit = NULL;
static ManagerRunningAs running_as = _MANAGER_RUNNING_AS_INVALID;
+
static bool dump_core = true;
+static bool crash_shell = false;
+static int crash_chvt = -1;
_noreturn static void freeze(void) {
for (;;)
else {
pid_t pid;
- log_warning("Caugh <%s>, dumping core.", strsignal(sig));
-
if ((pid = fork()) < 0)
- log_error("Caught <%s>, cannot dump core: %s", strsignal(sig), strerror(errno));
+ log_error("Caught <%s>, cannot fork for core dump: %s", strsignal(sig), strerror(errno));
else if (pid == 0) {
struct sigaction sa;
assert_not_reached("We shouldn't be here...");
_exit(1);
+
+ } else {
+ int status, r;
+
+ /* Order things nicely. */
+ if ((r = waitpid(pid, &status, 0)) < 0)
+ log_error("Caught <%s>, waitpid() failed: %s", strsignal(sig), strerror(errno));
+ else if (!WCOREDUMP(status))
+ log_error("Caught <%s>, core dump failed.", strsignal(sig));
+ else
+ log_error("Caught <%s>, dumped core as pid %llu.", strsignal(sig), (unsigned long long) pid);
}
}
- log_error("Freezing execution.");
+ if (crash_chvt)
+ chvt(crash_chvt);
+
+ if (crash_shell) {
+ log_info("Executing crash shell in 10s...");
+ sleep(10);
+
+ execl("/bin/sh", "/bin/sh", NULL);
+ log_error("execl() failed: %s", strerror(errno));
+ }
+
+ log_info("Freezing execution.");
freeze();
}
if (log_set_max_level_from_string(word + 18) < 0)
log_warning("Failed to parse log level %s. Ignoring.", word + 18);
+ } else if (startswith(word, "systemd.dump_core=")) {
+ int r;
+
+ if ((r = parse_boolean(word + 18)) < 0)
+ log_warning("Failed to parse dump core switch %s, Ignoring.", word + 18);
+ else
+ dump_core = r;
+
+ } else if (startswith(word, "systemd.crash_shell=")) {
+ int r;
+
+ if ((r = parse_boolean(word + 20)) < 0)
+ log_warning("Failed to parse crash shell switch %s, Ignoring.", word + 20);
+ else
+ crash_shell = r;
+
+ } else if (startswith(word, "systemd.crash_chvt=")) {
+ int k;
+
+ if (safe_atoi(word + 19, &k) < 0)
+ log_warning("Failed to parse crash chvt switch %s, Ignoring.", word + 19);
+ else
+ crash_chvt = k;
+
+ } else if (startswith(word, "systemd.")) {
+
+ log_warning("Unknown kernel switch %s. Ignoring.", word);
+
+ log_info("Supported kernel switches:");
+ log_info("systemd.default=UNIT Default unit to start");
+ log_info("systemd.log_target=console|kmsg|syslog Log target");
+ log_info("systemd.log_level=LEVEL Log level");
+ 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");
+
} else {
unsigned i;
/* SysV compatibility */
-
for (i = 0; i < ELEMENTSOF(rlmap); i += 2)
if (streq(word, rlmap[i]))
return set_default_unit(rlmap[i+1]);
/* Make sure D-Bus doesn't fiddle with the SIGPIPE handlers */
dbus_connection_set_change_sigpipe(FALSE);
- /* Open the logging devices, if possible and necessary*/
+ /* Open the logging devices, if possible and necessary */
log_open_syslog();
log_open_kmsg();
- install_crash_handler();
- assert(!"esel");
+ /* Make sure we leave a core dump */
+ if (getpid() == 1)
+ install_crash_handler();
log_debug("systemd running in %s mode.", manager_running_as_to_string(running_as));