destroy_bus() flushes unwritten data for unprivileged managers so that queued messages are not lost when a connection is torn down. However, sd_bus_flush() first drives the connection to completion via bus_ensure_running(): for a connection still in OPENING or AUTHENTICATING this blocks the manager synchronously - a single-fd ppoll, the event loop is not running - until the peer answers or BUS_AUTH_TIMEOUT (= DEFAULT_TIMEOUT_USEC, 90 s by default) expires; a connection in HELLO blocks the same way on the Hello call's own method timeout. destroy_bus() is reached from four places: the disconnect handler, manager_recheck_dbus(), the failed-setup path in api_bus_instance_id_reply(), and bus_done() during normal shutdown or reexec (via manager_free()). Such a peer legitimately never answers: during session teardown, dbus.socket can be (or re-enter) listening while the D-Bus service behind it is hung or already gone, so connect() succeeds against the socket backlog and the authentication request is never read. The user manager then freezes mid-shutdown - or mid-reexec - for 90 s, with every remaining unit stop (or the reexec itself) gated behind it. This is the block traced in #16471 (2020, v245): the reporter's strace shows the manager hanging in a single-fd ppoll with an ~89 s timeout right after SIGTERM - bus_ensure_running() driving an AUTHENTICATING reconnection - and their summary attributes it to the flush. Their tested sd-bus-level patch (breaking the wait via a SIGTERM-set flag) was met with "a work-around once things are already bad, but we shouldn't even get in that state"; the same reply stated the expectation this commit implements - the manager "should normally protect itself ... and not issue dbus messages when the dbus service isn't fully up". bus_foreach_bus() already applies that principle in the other direction, skipping enqueue for connections that "haven't started yet" via the same sd_bus_is_ready() check.1166f4472d("core/dbus: do not block the manager on GetId during bus (re-)connection") removed the connect-time instance of the same class of block, in code added in 2025. The flush here is twelve years older: it dates back to the libsystemd-bus conversion (718db96199, 2013). Only flush when the connection is currently RUNNING. This does not change what gets delivered in the failure case this fixes: whatever a non-RUNNING connection's write queue holds (auth/Hello traffic, and any subscriber signal a per-unit or per-job bus_track attached without a readiness check) was never actually sent by the old code either - sd_bus_flush() calls bus_ensure_running() before it ever looks at the write queue, so a connection that times out without reaching RUNNING had its queued data silently discarded on close exactly as before, just after blocking for up to 90 s first rather than immediately. The one narrowing is a connection that would have completed authentication within the timeout window: previously such traffic could still reach the peer after the block; now it will not. Every destroy_bus() call site is reached only once the manager has already decided the connection is being torn down (disconnected, recognized as down, or the process itself exiting/reexecuting), so this narrowing does not trade a working delivery for a broken one. Fixes #16471
System and Service Manager
Details
Most documentation is available on systemd's website.
Assorted, older, general information about systemd can be found in the systemd Wiki.
Information about build requirements is provided in the README file.
Consult our NEWS file for information about what's new in the most recent systemd versions.
Please see the Code Map for information about this repository's layout and content.
Please see the Hacking guide for information on how to hack on systemd and test your modifications.
Please see our Contribution Guidelines for more information about filing GitHub Issues and posting GitHub Pull Requests.
When preparing patches for systemd, please follow our Coding Style Guidelines.
If you are looking for support, please contact our mailing list, join our IRC channel #systemd on libera.chat or Matrix channel
Stable branches with backported patches are available in the stable repo.
We have a security bug bounty program sponsored by the Sovereign Tech Fund hosted on YesWeHack
Repositories with distribution packages built from git main are available on OBS, and also repositories with packages built from the latest stable release
