#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"
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);
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;
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. */
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