resolve: stop timer event source and detach from browser when a dnssd service is removed

Otherwise, if the timer event source is enabled, a new query may be
invoked by the already removed service.

This also renames dns_remove_service() to dnssd_discovered_service_detach(),
and drops unused DnssdDiscoveredService.query.
This commit is contained in:
Yu Watanabe
2026-09-23 11:38:14 +09:00
parent 219abd95ae
commit 02f65ebead
2 changed files with 23 additions and 22 deletions
+23 -18
View File
@@ -108,6 +108,8 @@ static int mdns_maintenance_query(sd_event_source *s, uint64_t usec, void *userd
_cleanup_(dns_query_freep) DnsQuery *q = NULL;
int r;
assert(service->service_browser);
/* Check if the TTL state has reached the maximum value, then revisit
* cache */
if (service->rr_ttl_state++ == DNS_RECORD_TTL_STATE_100_PERCENT)
@@ -171,12 +173,10 @@ int dns_add_new_service(DnsServiceBrowser *sb, DnsResourceRecord *rr, int owner_
*s = (DnssdDiscoveredService) {
.n_ref = 1,
.service_browser = sb,
.rr = dns_resource_record_copy(rr),
.family = owner_family,
.ifindex = ifindex,
.until = until,
.query = NULL,
.rr_ttl_state = DNS_RECORD_TTL_STATE_80_PERCENT,
};
if (!s->rr)
@@ -221,34 +221,39 @@ int dns_add_new_service(DnsServiceBrowser *sb, DnsResourceRecord *rr, int owner_
"Failed to schedule mDNS maintenance query for DNS service: %m");
LIST_PREPEND(dns_services, sb->dns_services, s);
s->service_browser = sb;
TAKE_PTR(s);
return 0;
}
void dns_remove_service(DnsServiceBrowser *sb, DnssdDiscoveredService *service) {
assert(sb);
static DnssdDiscoveredService* dnssd_discovered_service_detach_impl(DnssdDiscoveredService *service) {
assert(service);
LIST_REMOVE(dns_services, sb->dns_services, service);
dnssd_discovered_service_unref(service);
}
DnssdDiscoveredService *dns_service_free(DnssdDiscoveredService *service) {
if (!service)
return NULL;
service->schedule_event = sd_event_source_disable_unref(service->schedule_event);
if (service->query && DNS_TRANSACTION_IS_LIVE(service->query->state))
dns_query_complete(service->query, DNS_TRANSACTION_ABORTED);
if (!service->service_browser)
return NULL; /* already detached */
LIST_REMOVE(dns_services, service->service_browser->dns_services, service);
service->service_browser = NULL;
return service; /* indicate that the service is detached. */
}
static void dnssd_discovered_service_detach(DnssdDiscoveredService *service) {
dnssd_discovered_service_unref(dnssd_discovered_service_detach_impl(service));
}
static DnssdDiscoveredService* dnssd_discovered_service_free(DnssdDiscoveredService *service) {
if (!service)
return NULL;
dnssd_discovered_service_detach_impl(service);
service->rr = dns_resource_record_unref(service->rr);
return mfree(service);
}
DEFINE_TRIVIAL_REF_UNREF_FUNC(DnssdDiscoveredService, dnssd_discovered_service, dns_service_free);
DEFINE_TRIVIAL_REF_UNREF_FUNC(DnssdDiscoveredService, dnssd_discovered_service, dnssd_discovered_service_free);
int mdns_service_update(DnssdDiscoveredService *service, DnsResourceRecord *rr, usec_t t, usec_t until) {
assert(service);
@@ -498,7 +503,7 @@ int mdns_manage_services_answer(DnsServiceBrowser *sb, DnsAnswer *answer, int ow
/* Capture ifindex before removing the service */
ifindex = service->ifindex;
dns_remove_service(sb, service);
dnssd_discovered_service_detach(service);
log_debug("Remove from the list %s, %s, %s, %s, %d",
strna(name),
@@ -904,7 +909,7 @@ static DnsServiceBrowser* dns_service_browser_detach_impl(DnsServiceBrowser *sb)
assert(!sb->manager == !sb->link);
while (sb->dns_services)
dns_remove_service(sb, sb->dns_services);
dnssd_discovered_service_detach(sb->dns_services);
sb->schedule_event = sd_event_source_disable_unref(sb->schedule_event);
@@ -33,7 +33,6 @@ struct DnssdDiscoveredService {
int ifindex;
usec_t until;
DnsRecordTTLState rr_ttl_state;
DnsQuery *query;
LIST_FIELDS(DnssdDiscoveredService, dns_services);
};
@@ -52,9 +51,6 @@ struct DnsServiceBrowser {
LIST_HEAD(DnssdDiscoveredService, dns_services);
};
void dns_remove_service(DnsServiceBrowser *sb, DnssdDiscoveredService *service);
DnssdDiscoveredService *dns_service_free(DnssdDiscoveredService *service);
void dns_service_browser_detach(DnsServiceBrowser *sb);
DECLARE_TRIVIAL_REF_UNREF_FUNC(DnsServiceBrowser, dns_service_browser);
DECLARE_TRIVIAL_REF_UNREF_FUNC(DnssdDiscoveredService, dnssd_discovered_service);