chiark / gitweb /
journal: hook up coredumping with journal
authorLennart Poettering <lennart@poettering.net>
Fri, 13 Jan 2012 23:37:35 +0000 (00:37 +0100)
committerLennart Poettering <lennart@poettering.net>
Sat, 14 Jan 2012 00:54:33 +0000 (01:54 +0100)
.gitignore
Makefile.am
configure.ac
src/.gitignore
src/journal/coredump.c [new file with mode: 0644]
src/systemd/sd-messages.h
sysctl.d/.gitignore [new file with mode: 0644]
sysctl.d/Makefile [new symlink]
sysctl.d/coredump.conf.in [new file with mode: 0644]

index c260210..011aece 100644 (file)
@@ -1,3 +1,4 @@
+/systemd-coredump
 /systemd-cat
 /systemd-rc-local-generator
 /libsystemd-id128.pc
index d94de56..607ae7e 100644 (file)
@@ -52,6 +52,7 @@ bashcompletiondir=$(sysconfdir)/bash_completion.d
 pkgsysconfdir=$(sysconfdir)/systemd
 userunitdir=$(prefix)/lib/systemd/user
 tmpfilesdir=$(prefix)/lib/tmpfiles.d
+sysctldir=$(prefix)/lib/sysctl.d
 usergeneratordir=$(pkglibexecdir)/user-generators
 pkgincludedir=$(includedir)/systemd
 
@@ -1397,6 +1398,27 @@ EXTRA_DIST += \
 CLEANFILES += \
        src/journal/journald-gperf.c
 
+if ENABLE_COREDUMP
+
+systemd_coredump_SOURCES = \
+        src/journal/coredump.c
+
+systemd_coredump_LDADD = \
+       libsystemd-basic.la \
+       libsystemd-journal.la \
+       libsystemd-login.la
+
+rootlibexec_PROGRAMS += \
+        systemd-coredump
+
+sysctl_DATA = \
+        sysctl.d/coredump.conf
+
+EXTRA_DIST += \
+        sysctl.d/coredump.conf.in
+
+endif
+
 # ------------------------------------------------------------------------------
 if ENABLE_BINFMT
 systemd_binfmt_SOURCES = \
@@ -2074,6 +2096,9 @@ units/%: units/%.in Makefile
 man/%: man/%.in Makefile
        $(SED_PROCESS)
 
+sysctl.d/%: sysctl.d/%.in Makefile
+       $(SED_PROCESS)
+
 %.pc: %.pc.in Makefile
        $(SED_PROCESS)
 
index 80d0156..194caa5 100644 (file)
@@ -372,6 +372,13 @@ if test "x$enable_localed" != "xno"; then
 fi
 AM_CONDITIONAL(ENABLE_LOCALED, [test "$have_localed" = "yes"])
 
+have_coredump=no
+AC_ARG_ENABLE(coredump, AS_HELP_STRING([--disable-coredump], [disable coredump hook]))
+if test "x$enable_coredump" != "xno"; then
+       have_coredump=yes
+fi
+AM_CONDITIONAL(ENABLE_COREDUMP, [test "$have_coredump" = "yes"])
+
 have_gtk=no
 AC_ARG_ENABLE(gtk, AS_HELP_STRING([--disable-gtk], [disable GTK tools]))
 if test "x$enable_gtk" != "xno"; then
@@ -646,6 +653,7 @@ AC_MSG_RESULT([
         hostnamed:               ${have_hostnamed}
         timedated:               ${have_timedated}
         localed:                 ${have_localed}
+        coredump:                ${have_coredump}
         plymouth:                ${have_plymouth}
         prefix:                  ${prefix}
         rootprefix:              ${with_rootprefix}
index ff2737b..c54c6f6 100644 (file)
@@ -1,3 +1,4 @@
+/*.pc
 load-fragment-gperf-nulstr.c
 load-fragment-gperf.c
 load-fragment-gperf.gperf
diff --git a/src/journal/coredump.c b/src/journal/coredump.c
new file mode 100644 (file)
index 0000000..f160270
--- /dev/null
@@ -0,0 +1,173 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+  This file is part of systemd.
+
+  Copyright 2012 Lennart Poettering
+
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  systemd is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <errno.h>
+#include <unistd.h>
+
+#include <systemd/sd-journal.h>
+#include <systemd/sd-login.h>
+
+#include "log.h"
+#include "util.h"
+
+#define COREDUMP_MAX (64*1024)
+
+enum {
+        ARG_PID = 1,
+        ARG_UID,
+        ARG_GID,
+        ARG_SIGNAL,
+        ARG_TIMESTAMP,
+        ARG_COMM,
+        _ARG_MAX
+};
+
+int main(int argc, char* argv[]) {
+        int r, j = 0;
+        char *p = NULL;
+        ssize_t n;
+        pid_t pid;
+        struct iovec iovec[14];
+        char *core_pid = NULL, *core_uid = NULL, *core_gid = NULL, *core_signal = NULL,
+                *core_timestamp = NULL, *core_comm = NULL, *core_exe = NULL, *core_unit = NULL,
+                *core_session = NULL, *core_message = NULL, *core_cmdline = NULL, *t;
+
+        log_set_target(LOG_TARGET_JOURNAL_OR_KMSG);
+        log_parse_environment();
+        log_open();
+
+        if (argc != _ARG_MAX) {
+                log_error("Invalid number of arguments passed from kernel.");
+                r = -EINVAL;
+                goto finish;
+        }
+
+        r = parse_pid(argv[ARG_PID], &pid);
+        if (r < 0) {
+                log_error("Failed to parse PID.");
+                r = -EINVAL;
+                goto finish;
+        }
+
+        p = malloc(9 + COREDUMP_MAX);
+        if (!p) {
+                log_error("Out of memory");
+                r = -ENOMEM;
+                goto finish;
+        }
+
+        memcpy(p, "COREDUMP=", 9);
+
+        n = loop_read(STDIN_FILENO, p + 9, COREDUMP_MAX, false);
+        if (n < 0) {
+                log_error("Failed to read core dump data: %s", strerror(-n));
+                r = (int) n;
+                goto finish;
+        }
+
+        zero(iovec);
+        iovec[j].iov_base = p;
+        iovec[j].iov_len = 9 + n;
+        j++;
+
+        core_pid = strappend("COREDUMP_PID=", argv[ARG_PID]);
+        if (core_pid)
+                IOVEC_SET_STRING(iovec[j++], core_pid);
+
+        core_uid = strappend("COREDUMP_UID=", argv[ARG_UID]);
+        if (core_uid)
+                IOVEC_SET_STRING(iovec[j++], core_uid);
+
+        core_gid = strappend("COREDUMP_GID=", argv[ARG_GID]);
+        if (core_gid)
+                IOVEC_SET_STRING(iovec[j++], core_gid);
+
+        core_signal = strappend("COREDUMP_SIGNAL=", argv[ARG_SIGNAL]);
+        if (core_signal)
+                IOVEC_SET_STRING(iovec[j++], core_signal);
+
+        core_comm = strappend("COREDUMP_COMM=", argv[ARG_COMM]);
+        if (core_comm)
+                IOVEC_SET_STRING(iovec[j++], core_comm);
+
+        if (sd_pid_get_session(pid, &t) >= 0) {
+                core_session = strappend("COREDUMP_SESSION=", t);
+                free(t);
+
+                if (core_session)
+                        IOVEC_SET_STRING(iovec[j++], core_session);
+        }
+
+        if (sd_pid_get_unit(pid, &t) >= 0) {
+                core_unit = strappend("COREDUMP_UNIT=", t);
+                free(t);
+
+                if (core_unit)
+                        IOVEC_SET_STRING(iovec[j++], core_unit);
+        }
+
+        if (get_process_exe(pid, &t) >= 0) {
+                core_exe = strappend("COREDUMP_EXE=", t);
+                free(t);
+
+                if (core_exe)
+                        IOVEC_SET_STRING(iovec[j++], core_exe);
+        }
+
+        if (get_process_cmdline(pid, LINE_MAX, false, &t) >= 0) {
+                core_cmdline = strappend("COREDUMP_CMDLINE=", t);
+                free(t);
+
+                if (core_cmdline)
+                        IOVEC_SET_STRING(iovec[j++], core_cmdline);
+        }
+
+        core_timestamp = join("COREDUMP_TIMESTAMP=", argv[ARG_TIMESTAMP], "000000", NULL);
+        if (core_timestamp)
+                IOVEC_SET_STRING(iovec[j++], core_timestamp);
+
+        IOVEC_SET_STRING(iovec[j++], "MESSAGE_ID=fc2e22bc6ee647b6b90729ab34a250b1");
+        IOVEC_SET_STRING(iovec[j++], "PRIORITY=2");
+
+        core_message = join("MESSAGE=Process ", argv[ARG_PID], " (", argv[ARG_COMM], ") dumped core.", NULL);
+        if (core_message)
+                IOVEC_SET_STRING(iovec[j++], core_message);
+
+        r = sd_journal_sendv(iovec, j);
+        if (r < 0)
+                log_error("Failed to send coredump: %s", strerror(-r));
+
+finish:
+        free(p);
+        free(core_pid);
+        free(core_uid);
+        free(core_gid);
+        free(core_signal);
+        free(core_timestamp);
+        free(core_comm);
+        free(core_exe);
+        free(core_cmdline);
+        free(core_unit);
+        free(core_session);
+        free(core_message);
+
+        return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
+}
index 5fd1aa7..c5ac3ab 100644 (file)
@@ -32,6 +32,8 @@ extern "C" {
 #define SD_MESSAGE_JOURNAL_STOP    SD_ID128_MAKE(d9,3f,b3,c9,c2,4d,45,1a,97,ce,a6,15,ce,59,c0,0b)
 #define SD_MESSAGE_JOURNAL_DROPPED SD_ID128_MAKE(a5,96,d6,fe,7b,fa,49,94,82,8e,72,30,9e,95,d6,1e)
 
+#define SD_MESSAGE_COREDUMP        SD_ID128_MAKE(fc,2e,22,bc,6e,e6,47,b6,b9,07,29,ab,34,a2,50,b1)
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/sysctl.d/.gitignore b/sysctl.d/.gitignore
new file mode 100644 (file)
index 0000000..7563539
--- /dev/null
@@ -0,0 +1 @@
+/coredump.conf
diff --git a/sysctl.d/Makefile b/sysctl.d/Makefile
new file mode 120000 (symlink)
index 0000000..bd10475
--- /dev/null
@@ -0,0 +1 @@
+../src/Makefile
\ No newline at end of file
diff --git a/sysctl.d/coredump.conf.in b/sysctl.d/coredump.conf.in
new file mode 100644 (file)
index 0000000..ab19b1e
--- /dev/null
@@ -0,0 +1,10 @@
+#  This file is part of systemd.
+#
+#  systemd is free software; you can redistribute it and/or modify it
+#  under the terms of the GNU General Public License as published by
+#  the Free Software Foundation; either version 2 of the License, or
+#  (at your option) any later version.
+
+# See sysctl.d(5) for details
+
+kernel.core_pattern=|@rootlibexecdir@/systemd-coredump %p %u %g %s %t %e