From: Wouter Wijngaards Date: Thu, 1 Nov 2007 14:39:50 +0000 (+0000) Subject: alloc id overflow handling. X-Git-Tag: release-0.6~15 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d2892aa5abbd54ec7927f5e1a6ee1998a9d71e5e;p=thirdparty%2Funbound.git alloc id overflow handling. git-svn-id: file:///svn/unbound/trunk@729 be551aaa-1e26-0410-a405-d3ace91eadb9 --- diff --git a/checkconf/worker_cb.c b/checkconf/worker_cb.c index 29eaff96c..7f1445017 100644 --- a/checkconf/worker_cb.c +++ b/checkconf/worker_cb.c @@ -101,3 +101,9 @@ struct outbound_entry* worker_send_query(uint8_t* ATTR_UNUSED(qname), log_assert(0); return 0; } + +void +worker_alloc_cleanup(void* ATTR_UNUSED(arg)) +{ + log_assert(0); +} diff --git a/daemon/worker.c b/daemon/worker.c index 80a92f927..64ee700a3 100644 --- a/daemon/worker.c +++ b/daemon/worker.c @@ -938,6 +938,7 @@ worker_init(struct worker* worker, struct config_file *cfg, server_stats_init(&worker->stats); alloc_init(&worker->alloc, &worker->daemon->superalloc, worker->thread_num); + alloc_set_id_cleanup(&worker->alloc, &worker_alloc_cleanup, worker); worker->env = *worker->daemon->env; worker->env.worker = worker; worker->env.send_packet = &worker_send_packet; @@ -1044,3 +1045,11 @@ worker_send_query(uint8_t* qname, size_t qnamelen, uint16_t qtype, } return e; } + +void +worker_alloc_cleanup(void* arg) +{ + struct worker* worker = (struct worker*)arg; + slabhash_clear(&worker->env.rrset_cache->table); + slabhash_clear(worker->env.msg_cache); +} diff --git a/daemon/worker.h b/daemon/worker.h index abf0b58fe..94d1c65e6 100644 --- a/daemon/worker.h +++ b/daemon/worker.h @@ -214,4 +214,7 @@ int worker_handle_reply(struct comm_point* c, void* arg, int error, int worker_handle_service_reply(struct comm_point* c, void* arg, int error, struct comm_reply* reply_info); +/** cleanup the cache to remove all rrset IDs from it, arg is worker */ +void worker_alloc_cleanup(void* arg); + #endif /* DAEMON_WORKER_H */ diff --git a/doc/Changelog b/doc/Changelog index 8709e9410..e3afd7d9b 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -5,6 +5,8 @@ that checking the passwd entry still works. - minor touch up of clear() hashtable function. - VERB_DETAIL prints out what chdir, username, chroot is being done. + - when id numbers run out, caches are cleared, as in design notes. + Tested with a mock setup with very few bits in id, it worked. 31 October 2007: Wouter - cache-max-ttl config option. diff --git a/util/alloc.c b/util/alloc.c index 113f6a737..19a51ba27 100644 --- a/util/alloc.c +++ b/util/alloc.c @@ -43,6 +43,7 @@ #include "util/alloc.h" #include "util/regional.h" #include "util/data/packed_rrset.h" +#include "util/fptr_wlist.h" /** custom size of cached regional blocks */ #define ALLOC_REG_SIZE 16384 @@ -109,6 +110,8 @@ alloc_init(struct alloc_cache* alloc, struct alloc_cache* super, alloc->max_reg_blocks = 100; alloc->num_reg_blocks = 0; alloc->reg_list = NULL; + alloc->cleanup = NULL; + alloc->cleanup_arg = NULL; if(alloc->super) prealloc_blocks(alloc, alloc->max_reg_blocks); if(!alloc->super) { @@ -165,8 +168,10 @@ alloc_get_id(struct alloc_cache* alloc) { uint64_t id = alloc->next_id++; if(id == alloc->last_id) { - /* TODO: clear the rrset cache */ - log_warn("Out of ids. Clearing cache."); + log_warn("rrset alloc: out of 64bit ids. Clearing cache."); + fptr_whitelist_alloc_cleanup(alloc->cleanup); + (*alloc->cleanup)(alloc->cleanup_arg); + /* start back at first number */ /* like in alloc_init*/ alloc->next_id = (uint64_t)alloc->thread_num; alloc->next_id <<= THRNUM_SHIFT; /* in steps for comp. */ @@ -317,6 +322,14 @@ alloc_reg_release(struct alloc_cache* alloc, struct regional* r) alloc->num_reg_blocks++; } +void +alloc_set_id_cleanup(struct alloc_cache* alloc, void (*cleanup)(void*), + void* arg) +{ + alloc->cleanup = cleanup; + alloc->cleanup_arg = arg; +} + /** global debug value to keep track of total memory mallocs */ size_t unbound_mem_alloc = 0; /** global debug value to keep track of total memory frees */ diff --git a/util/alloc.h b/util/alloc.h index 8bba43e5d..6b54a9dfc 100644 --- a/util/alloc.h +++ b/util/alloc.h @@ -84,6 +84,10 @@ struct alloc_cache { uint64_t next_id; /** last id number possible */ uint64_t last_id; + /** what function to call to cleanup when last id is reached */ + void (*cleanup)(void*); + /** user arg for cleanup */ + void* cleanup_arg; /** how many regional blocks to keep back max */ size_t max_reg_blocks; @@ -162,4 +166,14 @@ struct regional* alloc_reg_obtain(struct alloc_cache* alloc); */ void alloc_reg_release(struct alloc_cache* alloc, struct regional* r); +/** + * Set cleanup on ID overflow callback function. This should remove all + * RRset ID references from the program. Clear the caches. + * @param alloc: the alloc + * @param cleanup: the callback function, called as cleanup(arg). + * @param arg: user argument to callback function. + */ +void alloc_set_id_cleanup(struct alloc_cache* alloc, void (*cleanup)(void*), + void* arg); + #endif /* UTIL_ALLOC_H */ diff --git a/util/fptr_wlist.c b/util/fptr_wlist.c index d90be69df..ac67b6e53 100644 --- a/util/fptr_wlist.c +++ b/util/fptr_wlist.c @@ -294,3 +294,10 @@ fptr_whitelist_mod_get_mem(size_t (*fptr)(struct module_env* env, int id)) else if(fptr == &val_get_mem) return 1; return 0; } + +int +fptr_whitelist_alloc_cleanup(void (*fptr)(void*)) +{ + if(fptr == &worker_alloc_cleanup) return 1; + return 0; +} diff --git a/util/fptr_wlist.h b/util/fptr_wlist.h index 89e3672b0..b3cebef68 100644 --- a/util/fptr_wlist.h +++ b/util/fptr_wlist.h @@ -264,4 +264,12 @@ int fptr_whitelist_mod_clear(void (*fptr)(struct module_qstate* qstate, */ int fptr_whitelist_mod_get_mem(size_t (*fptr)(struct module_env* env, int id)); +/** + * Check function pointer whitelist for alloc clear on id overflow call values. + * + * @param fptr: function pointer to check. + * @return false if not in whitelist. + */ +int fptr_whitelist_alloc_cleanup(void (*fptr)(void*)); + #endif /* UTIL_FPTR_WLIST_H */