Skip to content

Commit 6a61f25

Browse files
committed
Fix journal-gatewayd returning duplicated lines when following logs (#4124)
When following logs in Home Assitant frontend, the last line may be duplicated over time when no new lines are added. This is because systemd-journal-gatewayd incorrectly processed the num_skip part of the Range header, always returning the last entry even when it should have been skipped. Backport the patch for Systemd that processes the header correctly. Fixes #4101 (cherry picked from commit 4a4da64)
1 parent 83e85d9 commit 6a61f25

File tree

1 file changed

+73
-0
lines changed

1 file changed

+73
-0
lines changed
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
From 56e744bc45713ef7575032cfdb20073013ec0a8d Mon Sep 17 00:00:00 2001
2+
From: =?UTF-8?q?Jan=20=C4=8Cerm=C3=A1k?= <[email protected]>
3+
Date: Tue, 24 Jun 2025 18:54:44 +0200
4+
Subject: [PATCH] journal-gatewayd: fix handling of num_skip pointing beyond
5+
the last entry
6+
7+
When `num_skip` is supplied to the `Range` header, journal-gatewayd
8+
always returns the very last record even though it should have been
9+
skipped. This is because the `sd_journal_next_skip` always returns
10+
non-zero value on the first call, leading to one iteration of the
11+
`request_reader_entries` returning the last record.
12+
13+
To avoid this unexpected behavior, check that the number of lines we
14+
have skipped by is not lower than the requested skip value. If it is,
15+
then it means there are lines which should not be returned now -
16+
decrement the n_skip counter then and return from the function, closing
17+
the stream if follow flag is not set.
18+
19+
Fixes #37954
20+
---
21+
(Backported for v256.x)
22+
Signed-off-by: Jan Čermák <[email protected]>
23+
Upstream: https://github.com/systemd/systemd/pull/37955
24+
---
25+
src/journal-remote/journal-gatewayd.c | 16 ++++++++++++++--
26+
test/units/TEST-04-JOURNAL.journal-gatewayd.sh | 6 ++++++
27+
2 files changed, 20 insertions(+), 2 deletions(-)
28+
29+
diff --git a/src/journal-remote/journal-gatewayd.c b/src/journal-remote/journal-gatewayd.c
30+
index 0661ecb1cf..5bce48d485 100644
31+
--- a/src/journal-remote/journal-gatewayd.c
32+
+++ b/src/journal-remote/journal-gatewayd.c
33+
@@ -181,9 +181,21 @@ static ssize_t request_reader_entries(
34+
35+
if (m->n_skip < 0)
36+
r = sd_journal_previous_skip(m->journal, (uint64_t) -m->n_skip + 1);
37+
- else if (m->n_skip > 0)
38+
+ else if (m->n_skip > 0) {
39+
r = sd_journal_next_skip(m->journal, (uint64_t) m->n_skip + 1);
40+
- else
41+
+ if (r < 0) {
42+
+ log_error_errno(r, "Failed to skip journal entries: %m");
43+
+ return MHD_CONTENT_READER_END_WITH_ERROR;
44+
+ }
45+
+ /* We skipped beyond the end, make sure entries between the cursor and n_skip offset
46+
+ * from it are not returned. */
47+
+ if (r < m->n_skip + 1) {
48+
+ m->n_skip -= r;
49+
+ if (m->follow)
50+
+ return 0;
51+
+ return MHD_CONTENT_READER_END_OF_STREAM;
52+
+ }
53+
+ } else
54+
r = sd_journal_next(m->journal);
55+
56+
if (r < 0) {
57+
diff --git a/test/units/TEST-04-JOURNAL.journal-gatewayd.sh b/test/units/TEST-04-JOURNAL.journal-gatewayd.sh
58+
index ef85dc17c6..b6dc860b63 100755
59+
--- a/test/units/TEST-04-JOURNAL.journal-gatewayd.sh
60+
+++ b/test/units/TEST-04-JOURNAL.journal-gatewayd.sh
61+
@@ -82,6 +82,12 @@ timeout 5 curl -LSfs \
62+
--header "Range: entries=:-20:10" \
63+
http://localhost:19531/entries?follow >"$LOG_FILE"
64+
jq -se "length == 10" "$LOG_FILE"
65+
+# Test positive skip beyond the last entry
66+
+curl -LSfs \
67+
+ --header "Accept: application/json" \
68+
+ --header "Range: entries=$TEST_CURSOR:1:1" \
69+
+ http://localhost:19531/entries?SYSLOG_IDENTIFIER="$TEST_TAG" >"$LOG_FILE"
70+
+jq -se "length == 0" "$LOG_FILE"
71+
# Check if the specified cursor refers to an existing entry and return just that entry
72+
curl -LSfs \
73+
--header "Accept: application/json" \

0 commit comments

Comments
 (0)