summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/basic/log.c2
-rw-r--r--src/basic/log.h4
-rw-r--r--src/journal/journald-kmsg.c23
-rw-r--r--src/journal/journald-server.c8
-rw-r--r--src/journal/journald-server.h2
5 files changed, 33 insertions, 6 deletions
diff --git a/src/basic/log.c b/src/basic/log.c
index 983e5bc69c..7bc2f28007 100644
--- a/src/basic/log.c
+++ b/src/basic/log.c
@@ -358,7 +358,7 @@ void log_forget_fds(void) {
}
void log_set_max_level(int level) {
- assert((level & LOG_PRIMASK) == level);
+ assert(level == LOG_NULL || (level & LOG_PRIMASK) == level);
log_max_level = level;
}
diff --git a/src/basic/log.h b/src/basic/log.h
index b34bdffd1b..3bec4131a7 100644
--- a/src/basic/log.h
+++ b/src/basic/log.h
@@ -27,6 +27,10 @@ typedef enum LogTarget{
_LOG_TARGET_INVALID = -EINVAL,
} LogTarget;
+/* This log level disables logging completely. It can only be passed to log_set_max_level() and cannot be
+ * used a regular log level. */
+#define LOG_NULL (LOG_EMERG - 1)
+
/* Note to readers: << and >> have lower precedence than & and | */
#define SYNTHETIC_ERRNO(num) (1 << 30 | (num))
#define IS_SYNTHETIC_ERRNO(val) ((val) >> 30 & 1)
diff --git a/src/journal/journald-kmsg.c b/src/journal/journald-kmsg.c
index c96b84e61f..a9b745772b 100644
--- a/src/journal/journald-kmsg.c
+++ b/src/journal/journald-kmsg.c
@@ -19,6 +19,7 @@
#include "journald-kmsg.h"
#include "journald-server.h"
#include "journald-syslog.h"
+#include "log.h"
#include "parse-util.h"
#include "process-util.h"
#include "stdio-util.h"
@@ -106,6 +107,8 @@ void dev_kmsg_record(Server *s, char *p, size_t l) {
char *e, *f, *k;
uint64_t serial;
size_t pl;
+ int saved_log_max_level = INT_MAX;
+ ClientContext *c = NULL;
assert(s);
assert(p);
@@ -266,10 +269,16 @@ void dev_kmsg_record(Server *s, char *p, size_t l) {
else {
pl -= syslog_parse_identifier((const char**) &p, &identifier, &pid);
- /* Avoid any messages we generated ourselves via
- * log_info() and friends. */
- if (is_us(identifier, pid))
- goto finish;
+ /* Avoid logging any new messages when we're processing messages generated by ourselves via
+ * log_info() and friends to avoid infinite loops. */
+ if (is_us(identifier, pid)) {
+ if (!ratelimit_below(&s->kmsg_own_ratelimit))
+ return;
+
+ saved_log_max_level = log_get_max_level();
+ c = s->my_context;
+ log_set_max_level(LOG_NULL);
+ }
if (identifier) {
syslog_identifier = strjoin("SYSLOG_IDENTIFIER=", identifier);
@@ -287,7 +296,11 @@ void dev_kmsg_record(Server *s, char *p, size_t l) {
if (cunescape_length_with_prefix(p, pl, "MESSAGE=", UNESCAPE_RELAX, &message) >= 0)
iovec[n++] = IOVEC_MAKE_STRING(message);
- server_dispatch_message(s, iovec, n, ELEMENTSOF(iovec), NULL, NULL, priority, 0);
+
+ server_dispatch_message(s, iovec, n, ELEMENTSOF(iovec), c, NULL, priority, 0);
+
+ if (saved_log_max_level != INT_MAX)
+ log_set_max_level(saved_log_max_level);
finish:
for (j = 0; j < z; j++)
diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c
index ed53d32005..8e2990190b 100644
--- a/src/journal/journald-server.c
+++ b/src/journal/journald-server.c
@@ -65,6 +65,9 @@
#define DEFAULT_RATE_LIMIT_BURST 10000
#define DEFAULT_MAX_FILE_USEC USEC_PER_MONTH
+#define DEFAULT_KMSG_OWN_INTERVAL (5 * USEC_PER_SEC)
+#define DEFAULT_KMSG_OWN_BURST 50
+
#define RECHECK_SPACE_USEC (30*USEC_PER_SEC)
#define NOTIFY_SNDBUF_SIZE (8*1024*1024)
@@ -2212,6 +2215,11 @@ int server_init(Server *s, const char *namespace) {
.runtime_storage.name = "Runtime Journal",
.system_storage.name = "System Journal",
+
+ .kmsg_own_ratelimit = {
+ .interval = DEFAULT_KMSG_OWN_INTERVAL,
+ .burst = DEFAULT_KMSG_OWN_BURST,
+ },
};
r = set_namespace(s, namespace);
diff --git a/src/journal/journald-server.h b/src/journal/journald-server.h
index 53e75ff3b0..2e57905e03 100644
--- a/src/journal/journald-server.h
+++ b/src/journal/journald-server.h
@@ -16,6 +16,7 @@ typedef struct Server Server;
#include "journald-stream.h"
#include "list.h"
#include "prioq.h"
+#include "ratelimit.h"
#include "time-util.h"
#include "varlink.h"
@@ -142,6 +143,7 @@ struct Server {
uint64_t *kernel_seqnum;
bool dev_kmsg_readable:1;
+ RateLimit kmsg_own_ratelimit;
bool send_watchdog:1;
bool sent_notify_ready:1;