diff options
-rw-r--r-- | src/coredump/coredump.c | 32 | ||||
-rw-r--r-- | src/libsystemd/sd-journal/journal-send.c | 12 | ||||
-rw-r--r-- | src/libsystemd/sd-journal/journal-send.h | 4 |
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 |