summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2010-04-10 21:40:40 +0200
committerLennart Poettering <lennart@poettering.net>2010-04-10 21:40:40 +0200
commit97c4f35cd541baa2f985ff702a5b9f0b8b524a53 (patch)
tree1145f46e22ef6979a102cbaaa717bf975d81a715
parentdec1c02a34b4c5b9da5d2da2dcc09646cf1cef29 (diff)
main: install crash handler for creating core dumps
-rw-r--r--main.c64
1 files changed, 64 insertions, 0 deletions
diff --git a/main.c b/main.c
index 082ac4bb1b..4aa63cba77 100644
--- a/main.c
+++ b/main.c
@@ -28,6 +28,7 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <getopt.h>
+#include <signal.h>
#include "manager.h"
#include "log.h"
@@ -44,6 +45,66 @@ static enum {
static char *default_unit = NULL;
static ManagerRunningAs running_as = _MANAGER_RUNNING_AS_INVALID;
+static bool dump_core = true;
+
+_noreturn static void freeze(void) {
+ for (;;)
+ pause();
+}
+
+_noreturn static void crash(int sig) {
+
+ if (!dump_core)
+ log_error("Caught <%s>, not dumping core.", strsignal(sig));
+ 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));
+
+ else if (pid == 0) {
+ struct sigaction sa;
+ struct rlimit rl;
+
+ /* Enable default signal handler for core dump */
+ zero(sa);
+ sa.sa_handler = SIG_DFL;
+ assert_se(sigaction(sig, &sa, NULL) == 0);
+
+ /* Don't limit the core dump size */
+ zero(rl);
+ rl.rlim_cur = RLIM_INFINITY;
+ rl.rlim_max = RLIM_INFINITY;
+ setrlimit(RLIMIT_CORE, &rl);
+
+ /* Just to be sure... */
+ assert_se(chdir("/") == 0);
+
+ /* Raise the signal again */
+ raise(sig);
+
+ assert_not_reached("We shouldn't be here...");
+ _exit(1);
+ }
+ }
+
+ log_error("Freezing execution.");
+ freeze();
+}
+
+static void install_crash_handler(void) {
+ struct sigaction sa;
+
+ zero(sa);
+
+ sa.sa_handler = crash;
+ sa.sa_flags = SA_NODEFER;
+
+ assert_se(sigaction(SIGSEGV, &sa, NULL) == 0);
+ assert_se(sigaction(SIGABRT, &sa, NULL) == 0);
+}
static int set_default_unit(const char *u) {
char *c;
@@ -307,6 +368,9 @@ int main(int argc, char *argv[]) {
log_open_syslog();
log_open_kmsg();
+ install_crash_handler();
+ assert(!"esel");
+
log_debug("systemd running in %s mode.", manager_running_as_to_string(running_as));
if (running_as == MANAGER_INIT)