diff --git a/CHANGES b/CHANGES index c5247c9da4..b5ede0e132 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,6 @@ +2063. [bug] Change #1955 introduced a bug which caused the first + 'rndc flush' call to not free memory. [RT #16244] + 2062. [bug] 'dig +nssearch' was reusing a buffer before it had been returned by the socket code. [RT #16307] diff --git a/lib/dns/cache.c b/lib/dns/cache.c index 78d98c54e6..83f58e8e32 100644 --- a/lib/dns/cache.c +++ b/lib/dns/cache.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: cache.c,v 1.72 2006/07/19 00:24:17 marka Exp $ */ +/* $Id: cache.c,v 1.73 2006/08/01 01:03:27 marka Exp $ */ /*! \file */ @@ -108,6 +108,7 @@ struct cache_cleaner { clean in one increment */ cleaner_state_t state; /*% Idle/Busy. */ isc_boolean_t overmem; /*% The cache is in an overmem state. */ + isc_boolean_t replaceiterator; }; /*% @@ -566,6 +567,7 @@ cache_cleaner_init(dns_cache_t *cache, isc_taskmgr_t *taskmgr, cleaner->cache = cache; cleaner->iterator = NULL; cleaner->overmem = ISC_FALSE; + cleaner->replaceiterator = ISC_FALSE; cleaner->task = NULL; cleaner->cleaning_timer = NULL; @@ -815,6 +817,17 @@ incremental_cleaning_action(isc_task_t *task, isc_event_t *event) { if (cleaner->state == cleaner_s_done) { cleaner->state = cleaner_s_busy; end_cleaning(cleaner, event); + LOCK(&cleaner->cache->lock); + LOCK(&cleaner->lock); + if (cleaner->replaceiterator) { + dns_dbiterator_destroy(&cleaner->iterator); + (void) dns_db_createiterator(cleaner->cache->db, + ISC_FALSE, + &cleaner->iterator); + cleaner->replaceiterator = ISC_FALSE; + } + UNLOCK(&cleaner->lock); + UNLOCK(&cleaner->cache->lock); return; } @@ -1067,8 +1080,23 @@ dns_cache_flush(dns_cache_t *cache) { if (result != ISC_R_SUCCESS) 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); + } else { + if (cache->cleaner.state == cleaner_s_busy) + cache->cleaner.state = cleaner_s_done; + cache->cleaner.replaceiterator = ISC_TRUE; + } dns_db_detach(&cache->db); cache->db = db; + UNLOCK(&cache->cleaner.lock); + UNLOCK(&cache->lock); + return (ISC_R_SUCCESS); }