]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
journald: replace existing syslog event source before reopening
authorLuca Boccassi <luca.boccassi@gmail.com>
Tue, 7 Jul 2026 13:11:25 +0000 (14:11 +0100)
committerLuca Boccassi <luca.boccassi@gmail.com>
Tue, 7 Jul 2026 17:01:50 +0000 (18:01 +0100)
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

src/journal/journald-syslog.c
src/journal/test-journald-syslog.c

index 1a9aaf65ccb963101c0177204b1475fe393a0ccb..daab222f69a68cc3fe091026d313a6c4345c43db 100644 (file)
@@ -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");
index 3bb947af6ca66e26bab0ff32e83f444fb78286d0..3730162e5152c25a59a47b24ffdf88fa3a650dc4 100644 (file)
@@ -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);