summaryrefslogtreecommitdiff
path: root/src/coredump
diff options
context:
space:
mode:
authorDaan De Meyer <daan.j.demeyer@gmail.com>2022-07-13 14:46:33 +0200
committerLuca Boccassi <luca.boccassi@gmail.com>2022-07-15 19:27:00 +0100
commit5edf875b92b9986470d1499b6dd35dbca75f2854 (patch)
tree372fd6a944376c33fd1b00182eae0dc0949e599d /src/coredump
parent3acb6edef3857aa54ca9008fc3428a5f5e1a8bb7 (diff)
downloadsystemd-5edf875b92b9986470d1499b6dd35dbca75f2854.tar.gz
coredump: Try to write journald coredump metadata to the journal
Currently, if journald coredumps, the coredump is written to /var/lib/systemd/coredump but the coredump metadata is not written to the journal meaning we can't find out about the coredump's existence via the journal. This means that coredumpctl can't be used to work with journald coredumps, as well as any other tools that rely on journald to know about coredumps. To solve the issue, let's have systemd-coredump try to write systemd-journald coredump metadata to the journal. We have to be careful though, since if journald coredumps, there's no active reader on the receive end of the journal socket, so we have to make sure we don't deadlock trying to write to the socket. To avoid the deadlock, we put the socket in nonblocking mode before trying to write to it.
Diffstat (limited to 'src/coredump')
-rw-r--r--src/coredump/coredump.c32
1 files changed, 26 insertions, 6 deletions
diff --git a/src/coredump/coredump.c b/src/coredump/coredump.c
index 10a96ab568..3ec41a32c3 100644
--- a/src/coredump/coredump.c
+++ b/src/coredump/coredump.c
@@ -29,6 +29,7 @@
#include "fs-util.h"
#include "io-util.h"
#include "journal-importer.h"
+#include "journal-send.h"
#include "log.h"
#include "macro.h"
#include "main-func.h"
@@ -842,12 +843,10 @@ log:
core_message = strjoina(core_message, stacktrace ? "\n\n" : NULL, stacktrace);
- if (context->is_journald) {
- /* We cannot log to the journal, so just print the message.
- * The target was set previously to something safe. */
+ if (context->is_journald)
+ /* We might not be able to log to the journal, so let's always print the message to another
+ * log target. The target was set previously to something safe. */
log_dispatch(LOG_ERR, 0, core_message);
- return 0;
- }
(void) iovw_put_string_field(iovw, "MESSAGE=", core_message);
@@ -903,8 +902,29 @@ log:
coredump_size, arg_journal_size_max);
}
+ /* If journald is coredumping, we have to be careful that we don't deadlock when trying to write the
+ * coredump to the journal, so we put the journal socket in nonblocking mode before trying to write
+ * the coredump to the socket. */
+
+ if (context->is_journald) {
+ r = journal_fd_nonblock(true);
+ if (r < 0)
+ return log_error_errno(r, "Failed to make journal socket non-blocking: %m");
+ }
+
r = sd_journal_sendv(iovw->iovec, iovw->count);
- if (r < 0)
+
+ if (context->is_journald) {
+ int k;
+
+ k = journal_fd_nonblock(false);
+ if (k < 0)
+ return log_error_errno(k, "Failed to make journal socket blocking: %m");
+ }
+
+ if (r == -EAGAIN && context->is_journald)
+ log_warning_errno(r, "Failed to log journal coredump, ignoring: %m");
+ else if (r < 0)
return log_error_errno(r, "Failed to log coredump: %m");
return 0;