From d0328a8d142def70d1d189acd1e242287fd82721 Mon Sep 17 00:00:00 2001 From: Nick Date: Sat, 22 Aug 2026 23:37:19 +0400 Subject: [PATCH] fix(linux/publish): release the Avahi client when the poll loop stops `poll` and `client` are namespace-scope, so they are only destroyed at process exit. When publishing fails, create_services()' fail_guard calls simple_poll_quit() and the poll thread exits, but the client - and its libdbus connection to the system bus - stays open with its match rules installed and nobody left to read it. On dbus-broker the resulting queue is charged to the per-UID quota, so after a few days of uptime the quota is exhausted and the broker starts disconnecting unrelated peers owned by the same user. Release the client once simple_poll_loop() returns, and clear `group` with it since the entry group is owned by the client. --- src/platform/linux/publish.cpp | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/platform/linux/publish.cpp b/src/platform/linux/publish.cpp index 6ad3ce8db3b..5a2f45825fc 100644 --- a/src/platform/linux/publish.cpp +++ b/src/platform/linux/publish.cpp @@ -551,6 +551,8 @@ namespace platf::publish { if (poll_thread.joinable()) { poll_thread.join(); } + + poll.reset(); } }; @@ -581,6 +583,16 @@ namespace platf::publish { return nullptr; } - return std::make_unique(std::jthread {avahi::simple_poll_loop, poll.get()}); + return std::make_unique(std::jthread {[]() { + avahi::simple_poll_loop(poll.get()); + + // simple_poll_loop() returns only once publishing has stopped for good: either at + // shutdown, or because a failure path called simple_poll_quit(). Nothing services the + // client's D-Bus connection past this point, so release it here rather than leave it + // open and subscribed until the process exits. The entry group is owned by the client, + // so clear it too, otherwise a later start() would reuse a dangling pointer. + client.reset(); + group = nullptr; + }}); } } // namespace platf::publish