]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
4151. [bug] 'rndc flush' could cause a deadlock. [RT #39835]
authorMark Andrews <marka@isc.org>
Fri, 3 Jul 2015 00:17:33 +0000 (10:17 +1000)
committerMark Andrews <marka@isc.org>
Fri, 3 Jul 2015 00:17:57 +0000 (10:17 +1000)
CHANGES
lib/dns/cache.c

diff --git a/CHANGES b/CHANGES
index 114b9a36308a77dd72583cca5e56637f141b48ce..e9dd725cc543bde0cf0044d7202849e7cd2604cd 100644 (file)
--- 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]
 
index d0f05b9a09ab2117aee1cbe1dc567345a19a0d3e..3eeaaa86058d871552f2df6c85a20d774416625a 100644 (file)
@@ -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);
 }