static ManagerRunningAs running_as = _MANAGER_RUNNING_AS_INVALID;
static bool dump_core = true;
-static bool crash_shell = true;
+static bool crash_shell = false;
+static int crash_chvt = -1;
_noreturn static void freeze(void) {
for (;;)
}
}
+ if (crash_chvt)
+ chvt(crash_chvt);
+
if (crash_shell) {
log_info("Executing crash shell in 10s...");
sleep(10);
int r;
if ((r = parse_boolean(word + 18)) < 0)
- log_warning("Failed to parse dump core switch %s, Ignoring", word + 18);
+ log_warning("Failed to parse dump core switch %s, Ignoring.", word + 18);
else
dump_core = r;
int r;
if ((r = parse_boolean(word + 20)) < 0)
- log_warning("Failed to parse crash shell switch %s, Ignoring", word + 20);
+ 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("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;
#include <sys/stat.h>
#include <fcntl.h>
#include <dirent.h>
+#include <sys/ioctl.h>
+#include <linux/vt.h>
+#include <linux/tiocl.h>
#include "macro.h"
#include "util.h"
return false;
}
+int chvt(int vt) {
+ int fd, r = 0;
+
+ if ((fd = open("/dev/tty0", O_RDWR|O_NOCTTY|O_CLOEXEC)) < 0)
+ return -errno;
+
+ if (vt < 0) {
+ int tiocl[2] = {
+ TIOCL_GETKMSGREDIRECT,
+ 0
+ };
+
+ if (ioctl(fd, TIOCLINUX, tiocl) < 0)
+ return -errno;
+
+ vt = tiocl[0] <= 0 ? 1 : tiocl[0];
+ }
+
+ if (ioctl(fd, VT_ACTIVATE, vt) < 0)
+ r = -errno;
+
+ close_nointr(r);
+ return r;
+}
+
static const char *const ioprio_class_table[] = {
[IOPRIO_CLASS_NONE] = "none",
[IOPRIO_CLASS_RT] = "realtime",