core: add ReloadCount to Manager and bump on successful reload

Introduce a counter that tracks how many configuration reloads have
been successfully completed by the manager. The increment lives in
manager_reload() right after the "point of no return", so failed
reload attempts that bail out earlier (e.g. during serialization)
do not bump the counter.

It is accessible as a new ReloadCount property to
org.freedesktop.systemd1.Manager (D-Bus) and ReloadCount to
io.systemd.Manager.Describe (Varlink).

Also add an integration test for ReloadCount
that verifies that the new ReloadCount property increments by one per
daemon-reload, accumulates correctly across multiple reloads, and that
D-Bus and Varlink return identical values. Also tests that the counter
reset after a reexec.

Co-developed-by: Claude Opus 4.7 <noreply@anthropic.com>
Signed-off-by: Simon Lucido <simonlucido@meta.com>
This commit is contained in:
Simon Lucido
2026-05-03 10:23:55 +01:00
committed by Luca Boccassi
parent db28490c9f
commit d667b6b97f
8 changed files with 81 additions and 4 deletions
+51
View File
@@ -0,0 +1,51 @@
#!/usr/bin/env bash
# SPDX-License-Identifier: LGPL-2.1-or-later
set -eux
set -o pipefail
# Verify that the manager exposes a ReloadCount property that increments on
# every daemon-reload, resets to zero across daemon-reexec (since the count
# is not serialized), and is reachable over both D-Bus and Varlink.
read_count_dbus() {
busctl -j get-property org.freedesktop.systemd1 \
/org/freedesktop/systemd1 \
org.freedesktop.systemd1.Manager \
ReloadCount | jq -r '.data'
}
read_count_varlink() {
varlinkctl call /run/systemd/io.systemd.Manager \
io.systemd.Manager.Describe '{}' | jq -r '.runtime.ReloadCount'
}
# Sanity: both transports must agree.
dbus_count=$(read_count_dbus)
varlink_count=$(read_count_varlink)
(( dbus_count == varlink_count ))
# A single reload bumps the counter by one.
before=$(read_count_dbus)
systemctl daemon-reload
(( $(read_count_dbus) == before + 1 ))
# Multiple reloads accumulate.
systemctl daemon-reload
systemctl daemon-reload
(( $(read_count_dbus) == before + 3 ))
# And both transports still agree after the reload.
dbus_count=$(read_count_dbus)
varlink_count=$(read_count_varlink)
(( dbus_count == varlink_count ))
# A daemon-reexec resets the counter back to zero on both transports, since
# reload_count lives only in memory and is not carried across the reexec.
# `systemctl daemon-reexec` returns as soon as the old PID 1 closes its bus
# connection, which is before the new PID 1 has rebound /run/systemd/private.
# Use --watch-bind=yes to block on inotify until the new socket is live.
systemctl daemon-reexec
busctl --watch-bind=yes call org.freedesktop.systemd1 /org/freedesktop/systemd1 \
org.freedesktop.DBus.Peer Ping >/dev/null
(( $(read_count_dbus) == 0 ))
(( $(read_count_varlink) == 0 ))