From: Luca Boccassi Date: Tue, 7 Jul 2026 13:11:25 +0000 (+0100) Subject: journald: replace existing syslog event source before reopening X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=a77bd724d3f02fa261cf7d13434550a8c90479e8;p=thirdparty%2Fsystemd.git journald: replace existing syslog event source before reopening manager_open_syslog_socket() may be called again with an already open syslog fd. In that case the old syslog event source still watches the fd, so adding a new IO source for the same fd fails with -EEXIST and leaves the old source installed. Disable and unref the old event source before adding the replacement. This keeps reopening idempotent and avoids leaving a stale event source around. Follow-up for f9a810bedacf1da7c505c1786a2416d592665926 --- diff --git a/src/journal/journald-syslog.c b/src/journal/journald-syslog.c index 1a9aaf65ccb..daab222f69a 100644 --- a/src/journal/journald-syslog.c +++ b/src/journal/journald-syslog.c @@ -534,6 +534,8 @@ int manager_open_syslog_socket(Manager *m, const char *syslog_socket) { if (r < 0) return log_error_errno(r, "Failed to enable SO_TIMESTAMP: %m"); + m->syslog_event_source = sd_event_source_disable_unref(m->syslog_event_source); + r = sd_event_add_io(m->event, &m->syslog_event_source, m->syslog_fd, EPOLLIN, manager_process_datagram, m); if (r < 0) return log_error_errno(r, "Failed to add syslog sevrer fd to event loop: %m"); diff --git a/src/journal/test-journald-syslog.c b/src/journal/test-journald-syslog.c index 3bb947af6ca..3730162e515 100644 --- a/src/journal/test-journald-syslog.c +++ b/src/journal/test-journald-syslog.c @@ -1,9 +1,16 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ +#include "sd-event.h" + #include "alloc-util.h" +#include "fd-util.h" +#include "journald-manager.h" #include "journald-syslog.h" +#include "path-util.h" +#include "rm-rf.h" #include "syslog-util.h" #include "tests.h" +#include "tmpfile-util.h" static void test_syslog_parse_identifier_one( const char *str, @@ -71,4 +78,32 @@ TEST(syslog_parse_priority) { test_syslog_parse_priority_one("<111>", true, 111, 1); } +TEST(syslog_socket_replaces_existing_event_source) { + _cleanup_(rm_rf_physical_and_freep) char *tmpdir = NULL; + _cleanup_(sd_event_source_unrefp) sd_event_source *old_source = NULL; + _cleanup_(sd_event_unrefp) sd_event *event = NULL; + _cleanup_free_ char *syslog_socket = NULL; + Manager m = { + .syslog_fd = -EBADF, + }; + + ASSERT_OK(sd_event_new(&event)); + m.event = event; + + ASSERT_OK(mkdtemp_malloc("/tmp/test-journald-syslog-XXXXXX", &tmpdir)); + syslog_socket = path_join(tmpdir, "dev-log"); + ASSERT_NOT_NULL(syslog_socket); + + ASSERT_OK(manager_open_syslog_socket(&m, syslog_socket)); + old_source = sd_event_source_ref(m.syslog_event_source); + ASSERT_NOT_NULL(old_source); + + ASSERT_OK(manager_open_syslog_socket(&m, syslog_socket)); + ASSERT_OK_ZERO(sd_event_source_get_enabled(old_source, /* ret= */ NULL)); + ASSERT_TRUE(m.syslog_event_source != old_source); + + m.syslog_event_source = sd_event_source_unref(m.syslog_event_source); + m.syslog_fd = safe_close(m.syslog_fd); +} + DEFINE_TEST_MAIN(LOG_INFO);