summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/coredump/coredump.c32
-rw-r--r--src/libsystemd/sd-journal/journal-send.c12
-rw-r--r--src/libsystemd/sd-journal/journal-send.h4
3 files changed, 41 insertions, 7 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;
diff --git a/src/libsystemd/sd-journal/journal-send.c b/src/libsystemd/sd-journal/journal-send.c
index e1c40702d3..81e3c81a0b 100644
--- a/src/libsystemd/sd-journal/journal-send.c
+++ b/src/libsystemd/sd-journal/journal-send.c
@@ -66,6 +66,16 @@ retry:
return fd;
}
+int journal_fd_nonblock(bool nonblock) {
+ int r;
+
+ r = journal_fd();
+ if (r < 0)
+ return r;
+
+ return fd_nonblock(r, nonblock);
+}
+
#if VALGRIND
void close_journal_fd(void) {
/* Be nice to valgrind. This is not atomic. This must be used only in tests. */
@@ -318,7 +328,7 @@ _public_ int sd_journal_sendv(const struct iovec *iov, int n) {
if (errno == ENOENT)
return 0;
- if (!IN_SET(errno, EMSGSIZE, ENOBUFS))
+ if (!IN_SET(errno, EMSGSIZE, ENOBUFS, EAGAIN))
return -errno;
/* Message doesn't fit... Let's dump the data in a memfd or
diff --git a/src/libsystemd/sd-journal/journal-send.h b/src/libsystemd/sd-journal/journal-send.h
index cf8b199297..558d39a8c0 100644
--- a/src/libsystemd/sd-journal/journal-send.h
+++ b/src/libsystemd/sd-journal/journal-send.h
@@ -1,6 +1,10 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
+#include <stdbool.h>
+
+int journal_fd_nonblock(bool nonblock);
+
#if VALGRIND
void close_journal_fd(void);
#else