resolved: actually unregister DNS-SD services when the D-Bus client vanishes (#43578)

Since the D-Bus DNS-SD API was introduced in c3036641f0ed (v236),
`RegisterService()` has created an `sd_bus_track` object to destroy the
registered service when the registering client disconnects from the bus.
However, the track object is a `_cleanup_(sd_bus_track_unrefp)` local in
`bus_method_register_service()` that is never stored anywhere, so it is
destroyed again as soon as the method handler returns. The vanish
handler (`dnssd_registered_service_on_bus_track()`) has thus been dead
code for the past ~8 years.

The observable effect: services registered via D-Bus silently persist
after the client disconnects — unowned, advertised until resolved exits,
and impossible to re-register since the identifier stays taken
(`DNSSD_SERVICE_EXISTS`). At the same time, the registration doesn't
survive a resolved restart, so the current behavior is neither reliably
ephemeral nor reliably persistent. Noticed while reviewing a project
that (unknowingly relying on this bug) registers a service with a
one-shot `gdbus call` and expects it to persist.

This PR:
1. splits the goodbye/zone-removal logic out of
`bus_dnssd_method_unregister()` into a helper — the vanish path needs
the full teardown, not just `dnssd_registered_service_free()`, which
would leave the service's RRs published in the per-link mDNS zones;
2. stores the track object in `DnssdRegisteredService`, making client
tracking work as originally intended;
3. documents the lifetime semantics in `org.freedesktop.resolve1(5)`
(matching the equivalent Avahi D-Bus API, whose entry groups are
likewise bound to the client connection) and points to `*.dnssd` files
for registrations independent of a client's lifetime;
4. adds a TEST-75 case covering the connection-bound lifetime.

Note this is a behavioral change for fire-and-forget clients (one-shot
`busctl`/`gdbus` invocations). Arguably those were never working
reliably (registrations silently vanished on any resolved restart, and
stale entries blocked re-registration), but if this is deemed too risky,
the alternative would be to drop the dead tracking code and codify the
persist-until-exit behavior instead — I'd argue tracking as originally
intended is the better contract.

Verification: code compiles; the new integration test is included.
This commit is contained in:
Yu Watanabe
2026-09-03 06:14:31 +09:00
committed by GitHub
9 changed files with 260 additions and 42 deletions
+13
View File
@@ -4,6 +4,19 @@ CHANGES WITH 262 in spe:
Feature Removals and Incompatible Changes:
* DNS-SD services registered via systemd-resolved's D-Bus method
org.freedesktop.resolve1.Manager.RegisterService() are now
unregistered automatically when the client that registered them
disconnects from the bus, as originally intended and matching the
behavior of the equivalent Avahi API. Due to a bug the client
tracking never worked, and such services used to stay registered
until systemd-resolved exited (but did not survive a restart of the
daemon either). Clients must now keep their bus connection open for
as long as the service shall remain registered; one-shot
registrations, e.g. via busctl or gdbus, will be withdrawn again as
soon as the tool exits. To register a DNS-SD service independently
of a client's lifetime, use *.dnssd files, see systemd.dnssd(5).
* Meson options '-Dlibiptc=' (deprecated in v259), '-Dlibidn=',
'-Drc-local=', '-Dsysvinit-path=', and '-Dsysvrcnd-path=' (deprecated
in v260) have been removed.