mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-08-31 06:25:31 +00:00
Merge branch '3288-adb-cancelfind-race' into 'main'
lock find when unlinking adbname->finds in dns_adb_cancelfind() Closes #3288 See merge request isc-projects/bind9!6141
This commit is contained in:
@@ -2662,41 +2662,15 @@ dns_adb_destroyfind(dns_adbfind_t **findp) {
|
|||||||
free_adbfind(&find);
|
free_adbfind(&find);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
/*
|
||||||
dns_adb_cancelfind(dns_adbfind_t *find) {
|
* Caller must hold find lock.
|
||||||
isc_event_t *ev = NULL;
|
*/
|
||||||
isc_task_t *task = NULL;
|
static void
|
||||||
dns_adb_t *adb = NULL;
|
find_sendevent(dns_adbfind_t *find) {
|
||||||
dns_adbname_t *adbname = NULL;
|
|
||||||
dns_adbnamebucket_t *nbucket = NULL;
|
|
||||||
|
|
||||||
LOCK(&find->lock);
|
|
||||||
|
|
||||||
DP(DEF_LEVEL, "dns_adb_cancelfind on find %p", find);
|
|
||||||
|
|
||||||
adb = find->adb;
|
|
||||||
REQUIRE(DNS_ADB_VALID(adb));
|
|
||||||
|
|
||||||
REQUIRE(!FIND_EVENTFREED(find));
|
|
||||||
REQUIRE(FIND_WANTEVENT(find));
|
|
||||||
|
|
||||||
if (find->adbname == NULL) {
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
adbname = find->adbname;
|
|
||||||
find->adbname = NULL;
|
|
||||||
nbucket = adbname->bucket;
|
|
||||||
|
|
||||||
UNLOCK(&find->lock);
|
|
||||||
LOCK(&nbucket->lock);
|
|
||||||
ISC_LIST_UNLINK(adbname->finds, find, plink);
|
|
||||||
UNLOCK(&nbucket->lock);
|
|
||||||
LOCK(&find->lock);
|
|
||||||
|
|
||||||
cleanup:
|
|
||||||
if (!FIND_EVENTSENT(find)) {
|
if (!FIND_EVENTSENT(find)) {
|
||||||
ev = &find->event;
|
isc_event_t *ev = &find->event;
|
||||||
task = ev->ev_sender;
|
isc_task_t *task = ev->ev_sender;
|
||||||
|
|
||||||
ev->ev_sender = find;
|
ev->ev_sender = find;
|
||||||
ev->ev_type = DNS_EVENT_ADBCANCELED;
|
ev->ev_type = DNS_EVENT_ADBCANCELED;
|
||||||
ev->ev_destroy = event_freefind;
|
ev->ev_destroy = event_freefind;
|
||||||
@@ -2709,7 +2683,45 @@ cleanup:
|
|||||||
|
|
||||||
isc_task_sendanddetach(&task, (isc_event_t **)&ev);
|
isc_task_sendanddetach(&task, (isc_event_t **)&ev);
|
||||||
}
|
}
|
||||||
UNLOCK(&find->lock);
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
dns_adb_cancelfind(dns_adbfind_t *find) {
|
||||||
|
dns_adbname_t *adbname = NULL;
|
||||||
|
|
||||||
|
DP(DEF_LEVEL, "dns_adb_cancelfind on find %p", find);
|
||||||
|
|
||||||
|
REQUIRE(DNS_ADBFIND_VALID(find));
|
||||||
|
REQUIRE(DNS_ADB_VALID(find->adb));
|
||||||
|
|
||||||
|
LOCK(&find->lock);
|
||||||
|
REQUIRE(!FIND_EVENTFREED(find));
|
||||||
|
REQUIRE(FIND_WANTEVENT(find));
|
||||||
|
|
||||||
|
adbname = find->adbname;
|
||||||
|
|
||||||
|
if (adbname == NULL) {
|
||||||
|
find_sendevent(find);
|
||||||
|
UNLOCK(&find->lock);
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* Release the find lock, then acquire the bucket and find
|
||||||
|
* locks in that order, to match locking hierarchy
|
||||||
|
* elsewhere.
|
||||||
|
*/
|
||||||
|
UNLOCK(&find->lock);
|
||||||
|
LOCK(&adbname->bucket->lock);
|
||||||
|
LOCK(&find->lock);
|
||||||
|
|
||||||
|
if (find->adbname != NULL) {
|
||||||
|
ISC_LIST_UNLINK(adbname->finds, find, plink);
|
||||||
|
find->adbname = NULL;
|
||||||
|
}
|
||||||
|
find_sendevent(find);
|
||||||
|
|
||||||
|
UNLOCK(&find->lock);
|
||||||
|
UNLOCK(&adbname->bucket->lock);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
Reference in New Issue
Block a user