From 83028bc232c3e2494cf0a3236bf956cbdcc9165f Mon Sep 17 00:00:00 2001 From: Mark Andrews Date: Fri, 3 Jul 2015 10:17:33 +1000 Subject: [PATCH] 4151. [bug] 'rndc flush' could cause a deadlock. [RT #39835] --- CHANGES | 2 ++ lib/dns/cache.c | 24 ++++++++++++++++++------ 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/CHANGES b/CHANGES index 114b9a3630..e9dd725cc5 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,5 @@ +4151. [bug] 'rndc flush' could cause a deadlock. [RT #39835] + 4150. [bug] win32: listen-on-v6 { any; }; was not working. Apply minimal fix. [RT #39667] diff --git a/lib/dns/cache.c b/lib/dns/cache.c index d0f05b9a09..3eeaaa8605 100644 --- a/lib/dns/cache.c +++ b/lib/dns/cache.c @@ -1125,30 +1125,42 @@ cleaner_shutdown_action(isc_task_t *task, isc_event_t *event) { isc_result_t dns_cache_flush(dns_cache_t *cache) { - dns_db_t *db = NULL; + dns_db_t *db = NULL, *olddb; + dns_dbiterator_t *dbiterator = NULL, *olddbiterator = NULL; isc_result_t result; result = cache_create_db(cache, &db); if (result != ISC_R_SUCCESS) return (result); + result = dns_db_createiterator(db, ISC_FALSE, &dbiterator); + if (result != ISC_R_SUCCESS) { + dns_db_detach(&db); + return (result); + } + LOCK(&cache->lock); LOCK(&cache->cleaner.lock); if (cache->cleaner.state == cleaner_s_idle) { - if (cache->cleaner.iterator != NULL) - dns_dbiterator_destroy(&cache->cleaner.iterator); - (void) dns_db_createiterator(db, ISC_FALSE, - &cache->cleaner.iterator); + olddbiterator = cache->cleaner.iterator; + cache->cleaner.iterator = dbiterator; + dbiterator = NULL; } else { if (cache->cleaner.state == cleaner_s_busy) cache->cleaner.state = cleaner_s_done; cache->cleaner.replaceiterator = ISC_TRUE; } - dns_db_detach(&cache->db); + olddb = cache->db; cache->db = db; UNLOCK(&cache->cleaner.lock); UNLOCK(&cache->lock); + if (dbiterator != NULL) + dns_dbiterator_destroy(&dbiterator); + if (olddbiterator != NULL) + dns_dbiterator_destroy(&olddbiterator); + dns_db_detach(&olddb); + return (ISC_R_SUCCESS); }