Zone loading happens in a different task (zone->loadtask) than other
zone actions (zone->task). Thus, when zone_postload() is called in the
context of zone->loadtask, it may cause zone maintenance to be queued in
zone->task and another thread can then execute zone_maintenance() before
zone_postload() gets a chance to finish its work in the first thread.
This would not be a problem if zone_maintenance() accounted for this
possibility by locking the zone before checking the state of its
DNS_ZONEFLG_LOADPENDING flag. However, the zone is currently not locked
before the state of that flag is checked, which may prevent zone
maintenance from happening despite zone_postload() scheduling it. Fix
by locking the zone in zone_maintenance() before checking the state of
the zone's DNS_ZONEFLG_LOADPENDING flag.
(cherry picked from commit
56003e9f9f72c8be67d553f4dbd16eba849ca864)
const char me[] = "zone_maintenance";
isc_time_t now;
isc_result_t result;
- bool dumping;
+ bool dumping, load_pending;
REQUIRE(DNS_ZONE_VALID(zone));
ENTER;
/*
* Are we pending load/reload?
*/
- if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADPENDING))
+ LOCK_ZONE(zone);
+ load_pending = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADPENDING);
+ UNLOCK_ZONE(zone);
+
+ if (load_pending) {
return;
+ }
/*
* Configuring the view of this zone may have