summaryrefslogtreecommitdiff
path: root/src/journal/coredump.c
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2014-06-19 12:07:12 +0200
committerLennart Poettering <lennart@poettering.net>2014-06-19 12:38:45 +0200
commit8d4e028f1868c47864ec873d9f30c3ee961a8849 (patch)
tree8a16e81f48f49c2d5aa210d8992f0c7d4a8470c2 /src/journal/coredump.c
parent8271bd16ce9327834d8580e55bb5e4e0896fd98a (diff)
coredump: include stacktrace of coredumps in the log message
elfutils' libdw is maintained, can read DWARF debug data and appears to be the library of choice for generating backtraces today.
Diffstat (limited to 'src/journal/coredump.c')
-rw-r--r--src/journal/coredump.c38
1 files changed, 27 insertions, 11 deletions
diff --git a/src/journal/coredump.c b/src/journal/coredump.c
index 3365f9f146..f48f4e2c89 100644
--- a/src/journal/coredump.c
+++ b/src/journal/coredump.c
@@ -38,6 +38,7 @@
#include "journald-native.h"
#include "conf-parser.h"
#include "copy.h"
+#include "stacktrace.h"
#ifdef HAVE_ACL
#include <sys/acl.h>
@@ -290,6 +291,7 @@ static int allocate_journal_field(int fd, size_t size, char **ret, size_t *ret_s
_cleanup_free_ char *field = NULL;
ssize_t n;
+ assert(fd >= 0);
assert(ret);
assert(ret_size);
@@ -346,7 +348,8 @@ int main(int argc, char* argv[]) {
_cleanup_free_ 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, *coredump_data = NULL,
- *coredump_filename = NULL, *core_slice = NULL, *core_cgroup = NULL, *core_owner_uid = NULL;
+ *coredump_filename = NULL, *core_slice = NULL, *core_cgroup = NULL, *core_owner_uid = NULL,
+ *exe = NULL;
_cleanup_close_ int coredump_fd = -1;
@@ -365,7 +368,6 @@ int main(int argc, char* argv[]) {
* crashed and it might be journald which we'd rather not log
* to then. */
log_set_target(LOG_TARGET_KMSG);
- log_set_max_level(LOG_DEBUG);
log_open();
if (argc != _ARG_MAX) {
@@ -474,10 +476,8 @@ int main(int argc, char* argv[]) {
IOVEC_SET_STRING(iovec[j++], core_slice);
}
- if (get_process_exe(pid, &t) >= 0) {
- core_exe = strappend("COREDUMP_EXE=", t);
- free(t);
-
+ if (get_process_exe(pid, &exe) >= 0) {
+ core_exe = strappend("COREDUMP_EXE=", exe);
if (core_exe)
IOVEC_SET_STRING(iovec[j++], core_exe);
}
@@ -505,17 +505,15 @@ int main(int argc, char* argv[]) {
IOVEC_SET_STRING(iovec[j++], "MESSAGE_ID=fc2e22bc6ee647b6b90729ab34a250b1");
IOVEC_SET_STRING(iovec[j++], "PRIORITY=2");
- core_message = strjoin("MESSAGE=Process ", argv[ARG_PID], " (", argv[ARG_COMM], ") dumped core.", NULL);
- if (core_message)
- IOVEC_SET_STRING(iovec[j++], core_message);
-
/* Always stream the coredump to disk, if that's possible */
r = save_external_coredump(argv, uid, &coredump_filename, &coredump_fd, &coredump_size);
if (r < 0)
goto finish;
/* If we don't want to keep the coredump on disk, remove it
- * now, as later on we will lack the privileges for it. */
+ * now, as later on we will lack the privileges for
+ * it. However, we keep the fd to it, so that we can still
+ * process it and log it. */
r = maybe_remove_external_coredump(coredump_filename, coredump_size);
if (r < 0)
goto finish;
@@ -532,6 +530,24 @@ int main(int argc, char* argv[]) {
goto finish;
}
+#ifdef HAVE_ELFUTILS
+ /* Try to get a strack trace if we can */
+ if (coredump_size <= arg_process_size_max) {
+ _cleanup_free_ char *stacktrace = NULL;
+
+ r = coredump_make_stack_trace(coredump_fd, exe, &stacktrace);
+ if (r >= 0)
+ core_message = strjoin("MESSAGE=Process ", argv[ARG_PID], " (", argv[ARG_COMM], ") of user ", argv[ARG_UID], " dumped core.\n\n", stacktrace, NULL);
+ else
+ log_warning("Failed to generate stack trace: %s", strerror(-r));
+ }
+
+ if (!core_message)
+#endif
+ core_message = strjoin("MESSAGE=Process ", argv[ARG_PID], " (", argv[ARG_COMM], ") of user ", argv[ARG_UID], " dumped core.", NULL);
+ if (core_message)
+ IOVEC_SET_STRING(iovec[j++], core_message);
+
/* Optionally store the entire coredump in the journal */
if (IN_SET(arg_storage, COREDUMP_STORAGE_JOURNAL, COREDUMP_STORAGE_BOTH) &&
coredump_size <= (off_t) arg_journal_size_max) {