From: Jan Čermák Date: Wed, 30 Jul 2025 17:18:13 +0000 (+0200) Subject: journal-gatewayd: fix busy loop when following way beyond journal end X-Git-Tag: v258-rc2~30 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=db8b91980b9914564224fec1566f60c2961c6dc8;p=thirdparty%2Fsystemd.git journal-gatewayd: fix busy loop when following way beyond journal end Fix regression introduced in a7bfb9f76b96888d60b4f287f29dcbf758ba34c0, where busy loop can be started with a request for following logs with a range header set with num_skip value pointing beyond the end of the journal. In that case the reader callback returns 0 and is called immediately again, usually causing an endless loop that is not recovered even when new journal events are added. The bug does not occur if num_skip is not set - in that case if no journal entries matching the filters are added, the tight loop is avoided by the sd_journal_wait(). To fix the issue, when no matching journal events are available, set a flag and reuse the backoff mechanism using the sd_journal_wait(). Link: https://github.com/home-assistant/operating-system/issues/4190 --- diff --git a/src/journal-remote/journal-gatewayd.c b/src/journal-remote/journal-gatewayd.c index 4d574375996..97acab82b70 100644 --- a/src/journal-remote/journal-gatewayd.c +++ b/src/journal-remote/journal-gatewayd.c @@ -172,6 +172,7 @@ static ssize_t request_reader_entries( while (pos >= m->size) { off_t sz; + bool wait_for_events = false; /* End of this entry, so let's serialize the next * one */ @@ -192,9 +193,10 @@ static ssize_t request_reader_entries( * from it are not returned. */ if (r < m->n_skip + 1) { m->n_skip -= r; - if (m->follow) - return 0; - return MHD_CONTENT_READER_END_OF_STREAM; + + if (!m->follow) + return MHD_CONTENT_READER_END_OF_STREAM; + wait_for_events = true; } } else r = sd_journal_next(m->journal); @@ -203,20 +205,21 @@ static ssize_t request_reader_entries( log_error_errno(r, "Failed to advance journal pointer: %m"); return MHD_CONTENT_READER_END_WITH_ERROR; } else if (r == 0) { + if (!m->follow) + return MHD_CONTENT_READER_END_OF_STREAM; + wait_for_events = true; + } - if (m->follow) { - r = sd_journal_wait(m->journal, (uint64_t) JOURNAL_WAIT_TIMEOUT); - if (r < 0) { - log_error_errno(r, "Couldn't wait for journal event: %m"); - return MHD_CONTENT_READER_END_WITH_ERROR; - } - if (r == SD_JOURNAL_NOP) - break; - - continue; + if (wait_for_events) { + r = sd_journal_wait(m->journal, (uint64_t) JOURNAL_WAIT_TIMEOUT); + if (r < 0) { + log_error_errno(r, "Couldn't wait for journal event: %m"); + return MHD_CONTENT_READER_END_WITH_ERROR; } + if (r == SD_JOURNAL_NOP) + break; - return MHD_CONTENT_READER_END_OF_STREAM; + continue; } if (m->discrete) {