diff --git a/bin/check/named-checkconf.c b/bin/check/named-checkconf.c index e87d4a1457..9e59854638 100644 --- a/bin/check/named-checkconf.c +++ b/bin/check/named-checkconf.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: named-checkconf.c,v 1.28.18.10 2005/08/25 00:05:41 marka Exp $ */ +/* $Id: named-checkconf.c,v 1.28.18.11 2005/09/18 07:58:03 marka Exp $ */ /*! \file */ @@ -438,6 +438,8 @@ main(int argc, char **argv) { cfg_parser_destroy(&parser); + dns_name_destroy(); + isc_log_destroy(&logc); isc_hash_destroy(); diff --git a/bin/check/named-checkzone.c b/bin/check/named-checkzone.c index 4a56167e5a..0dfcbb06dc 100644 --- a/bin/check/named-checkzone.c +++ b/bin/check/named-checkzone.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: named-checkzone.c,v 1.29.18.11 2005/09/01 03:04:14 marka Exp $ */ +/* $Id: named-checkzone.c,v 1.29.18.12 2005/09/18 07:58:03 marka Exp $ */ /*! \file */ @@ -86,6 +86,7 @@ static void destroy(void) { if (zone != NULL) dns_zone_detach(&zone); + dns_name_destroy(); } /*% main processing routine */ diff --git a/bin/dig/dighost.c b/bin/dig/dighost.c index 86b331e68a..e7accc1542 100644 --- a/bin/dig/dighost.c +++ b/bin/dig/dighost.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: dighost.c,v 1.259.18.26 2005/09/09 06:22:05 marka Exp $ */ +/* $Id: dighost.c,v 1.259.18.27 2005/09/18 07:58:04 marka Exp $ */ /*! \file * \note @@ -3223,6 +3223,9 @@ destroy_libs(void) { void * ptr; dig_message_t *chase_msg; #endif +#ifdef WITH_IDN + isc_result_t result; +#endif debug("destroy_libs()"); if (global_task != NULL) { @@ -3254,6 +3257,13 @@ destroy_libs(void) { flush_server_list(); clear_searchlist(); + +#ifdef WITH_IDN + result = dns_name_settotextfilter(NULL); + check_result(result, "dns_name_settotextfilter"); +#endif + dns_name_destroy(); + if (commctx != NULL) { debug("freeing commctx"); isc_mempool_destroy(&commctx); diff --git a/bin/dnssec/dnssec-keygen.c b/bin/dnssec/dnssec-keygen.c index 8518749278..0bfcd53d4a 100644 --- a/bin/dnssec/dnssec-keygen.c +++ b/bin/dnssec/dnssec-keygen.c @@ -16,7 +16,7 @@ * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: dnssec-keygen.c,v 1.66.18.3 2005/04/29 00:15:20 marka Exp $ */ +/* $Id: dnssec-keygen.c,v 1.66.18.4 2005/09/18 07:58:05 marka Exp $ */ /*! \file */ @@ -409,6 +409,7 @@ main(int argc, char **argv) { cleanup_logging(&log); cleanup_entropy(&ectx); dst_lib_destroy(); + dns_name_destroy(); if (verbose > 10) isc_mem_stats(mctx, stdout); isc_mem_destroy(&mctx); diff --git a/bin/dnssec/dnssec-signzone.c b/bin/dnssec/dnssec-signzone.c index f763929691..0e23d575f4 100644 --- a/bin/dnssec/dnssec-signzone.c +++ b/bin/dnssec/dnssec-signzone.c @@ -16,7 +16,7 @@ * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: dnssec-signzone.c,v 1.177.18.12 2005/06/28 03:00:20 marka Exp $ */ +/* $Id: dnssec-signzone.c,v 1.177.18.13 2005/09/18 07:58:05 marka Exp $ */ /*! \file */ @@ -2150,6 +2150,7 @@ main(int argc, char *argv[]) { dst_lib_destroy(); isc_hash_destroy(); cleanup_entropy(&ectx); + dns_name_destroy(); if (verbose > 10) isc_mem_stats(mctx, stdout); isc_mem_destroy(&mctx); diff --git a/bin/named/main.c b/bin/named/main.c index d24f82b421..a217ce3565 100644 --- a/bin/named/main.c +++ b/bin/named/main.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: main.c,v 1.136.18.12 2005/09/05 00:18:10 marka Exp $ */ +/* $Id: main.c,v 1.136.18.13 2005/09/18 07:58:05 marka Exp $ */ /*! \file */ @@ -715,6 +715,8 @@ cleanup(void) { dlz_drivers_clear(); #endif + dns_name_destroy(); + isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN, ISC_LOG_NOTICE, "exiting"); ns_log_shutdown(); diff --git a/bin/nsupdate/nsupdate.c b/bin/nsupdate/nsupdate.c index ccf72d304b..f1895f83ef 100644 --- a/bin/nsupdate/nsupdate.c +++ b/bin/nsupdate/nsupdate.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: nsupdate.c,v 1.130.18.8 2005/04/27 05:00:38 sra Exp $ */ +/* $Id: nsupdate.c,v 1.130.18.9 2005/09/18 07:58:06 marka Exp $ */ /*! \file */ @@ -1927,6 +1927,9 @@ cleanup(void) { ddebug("Destroying hash context"); isc_hash_destroy(); + ddebug("Destroying name state"); + dns_name_destroy(); + ddebug("Destroying memory context"); if (memdebugging) isc_mem_stats(mctx, stderr); diff --git a/bin/rndc/rndc.c b/bin/rndc/rndc.c index 743a8ad5e4..1181a5af1a 100644 --- a/bin/rndc/rndc.c +++ b/bin/rndc/rndc.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: rndc.c,v 1.96.18.9 2005/04/27 05:00:39 sra Exp $ */ +/* $Id: rndc.c,v 1.96.18.10 2005/09/18 07:58:07 marka Exp $ */ /*! \file */ @@ -824,6 +824,8 @@ main(int argc, char **argv) { isc_mem_put(mctx, args, argslen); isccc_ccmsg_invalidate(&ccmsg); + dns_name_destroy(); + if (show_final_mem) isc_mem_stats(mctx, stderr); diff --git a/lib/dns/include/dns/name.h b/lib/dns/include/dns/name.h index 3c6b6549b8..a19091091e 100644 --- a/lib/dns/include/dns/name.h +++ b/lib/dns/include/dns/name.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: name.h,v 1.107.18.11 2005/09/09 06:22:08 marka Exp $ */ +/* $Id: name.h,v 1.107.18.12 2005/09/18 07:58:07 marka Exp $ */ #ifndef DNS_NAME_H #define DNS_NAME_H 1 @@ -1132,6 +1132,11 @@ dns_name_settotextfilter(dns_name_totextfilter_t proc); * Set / clear a thread specific function 'proc' to be called at the * end of dns_name_totext(). * + * Note: Under Windows you need to call "dns_name_settotextfilter(NULL);" + * prior to exiting the thread otherwise memory will be leaked. + * For other platforms, which are pthreads based, this is still a good + * idea but not required. + * * Returns *\li #ISC_R_SUCCESS *\li #ISC_R_UNEXPECTED @@ -1169,7 +1174,7 @@ dns_name_copy(dns_name_t *source, dns_name_t *dest, isc_buffer_t *target); isc_boolean_t dns_name_ishostname(const dns_name_t *name, isc_boolean_t wildcard); -/* +/*%< * Return if 'name' is a valid hostname. RFC 952 / RFC 1123. * If 'wildcard' is ISC_TRUE then allow the first label of name to * be a wildcard. @@ -1182,20 +1187,32 @@ dns_name_ishostname(const dns_name_t *name, isc_boolean_t wildcard); isc_boolean_t dns_name_ismailbox(const dns_name_t *name); -/* +/*%< * Return if 'name' is a valid mailbox. RFC 821. * * Requires: - * 'name' to be valid. + * \li 'name' to be valid. */ isc_boolean_t dns_name_internalwildcard(const dns_name_t *name); -/* +/*%< * Return if 'name' contains a internal wildcard name. * * Requires: - * 'name' to be valid. + * \li 'name' to be valid. + */ + +void +dns_name_destroy(void); +/*%< + * Cleanup dns_name_settotextfilter() / dns_name_totext() state. + * + * This should be called as part of the final cleanup process. + * + * Note: dns_name_settotextfilter(NULL); should be called for all + * threads which have called dns_name_settotextfilter() with a + * non-NULL arguement prior to calling dns_name_destroy(); */ ISC_LANG_ENDDECLS diff --git a/lib/dns/name.c b/lib/dns/name.c index 8f1eb34605..caeeb37e8b 100644 --- a/lib/dns/name.c +++ b/lib/dns/name.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: name.c,v 1.144.18.10 2005/09/10 01:09:29 marka Exp $ */ +/* $Id: name.c,v 1.144.18.11 2005/09/18 07:58:07 marka Exp $ */ /*! \file */ @@ -191,6 +191,9 @@ dns_fullname_hash(dns_name_t *name, isc_boolean_t case_sensitive); * dns_name_t to text post-conversion procedure. */ #ifdef ISC_PLATFORM_USETHREADS +static int thread_key_initialized = 0; +static isc_mutex_t thread_key_mutex; +static isc_mem_t *thread_key_mctx = NULL; static isc_thread_key_t totext_filter_proc_key; static isc_once_t once = ISC_ONCE_INIT; #else @@ -1277,8 +1280,49 @@ dns_name_fromtext(dns_name_t *name, isc_buffer_t *source, #ifdef ISC_PLATFORM_USETHREADS static void +free_specific(void *arg) { + dns_name_totextfilter_t *mem = arg; + isc_mem_put(thread_key_mctx, mem, sizeof(*mem)); + /* Stop use being called again. */ + (void)isc_thread_key_setspecific(totext_filter_proc_key, NULL); +} + +static void +thread_key_mutex_init(void) { + RUNTIME_CHECK(isc_mutex_init(&thread_key_mutex) == ISC_R_SUCCESS); +} + +static isc_result_t totext_filter_proc_key_init(void) { - RUNTIME_CHECK(isc_key_create(&totext_filter_proc_key, free) == 0); + isc_result_t result; + + /* + * We need the call to isc_once_do() to support profiled mutex + * otherwise thread_key_mutex could be initialized at compile time. + */ + result = isc_once_do(&once, thread_key_mutex_init); + if (result != ISC_R_SUCCESS) + return (result); + + if (!thread_key_initialized) { + LOCK(&thread_key_mutex); + if (thread_key_mctx == NULL) + result = isc_mem_create2(0, 0, &thread_key_mctx, 0); + if (result != ISC_R_SUCCESS) + goto unlock; + isc_mem_setdestroycheck(thread_key_mctx, ISC_FALSE); + + if (!thread_key_initialized && + isc_thread_key_create(&totext_filter_proc_key, + free_specific) != 0) { + result = ISC_R_FAILURE; + isc_mem_detach(&thread_key_mctx); + } else + thread_key_initialized = 1; + unlock: + UNLOCK(&thread_key_mutex); + } + return (result); } #endif @@ -1308,7 +1352,7 @@ dns_name_totext(dns_name_t *name, isc_boolean_t omit_final_dot, REQUIRE(ISC_BUFFER_VALID(target)); #ifdef ISC_PLATFORM_USETHREADS - result = isc_once_do(&once, totext_filter_proc_key_init); + result = totext_filter_proc_key_init(); if (result != ISC_R_SUCCESS) return (result); #endif @@ -1445,7 +1489,7 @@ dns_name_totext(dns_name_t *name, isc_boolean_t omit_final_dot, #ifdef ISC_PLATFORM_USETHREADS - mem = isc_key_getspecific(totext_filter_proc_key); + mem = isc_thread_key_getspecific(totext_filter_proc_key); if (mem) totext_filter_proc = *mem; #endif @@ -2238,8 +2282,9 @@ dns_name_settotextfilter(dns_name_totextfilter_t proc) { #ifdef ISC_PLATFORM_USETHREADS isc_result_t result; dns_name_totextfilter_t *mem; + int res; - result = isc_once_do(&once, totext_filter_proc_key_init); + result = totext_filter_proc_key_init(); if (result != ISC_R_SUCCESS) return (result); @@ -2247,28 +2292,27 @@ dns_name_settotextfilter(dns_name_totextfilter_t proc) { * If we already have been here set / clear as appropriate. * Otherwise allocate memory. */ - mem = isc_key_getspecific(totext_filter_proc_key); + mem = isc_thread_key_getspecific(totext_filter_proc_key); if (mem != NULL && proc != NULL) { *mem = proc; return (ISC_R_SUCCESS); } if (proc == NULL) { - free(mem); - if (isc_key_setspecific(totext_filter_proc_key, NULL) != 0) + isc_mem_put(thread_key_mctx, mem, sizeof(*mem)); + res = isc_thread_key_setspecific(totext_filter_proc_key, NULL); + if (res != 0) result = ISC_R_UNEXPECTED; return (result); } - /* - * We use malloc because Windows can't automatically free the - * memory and we don't want to trigger a INSIST at exit. - */ - mem = malloc(sizeof(dns_name_totextfilter_t)); + mem = isc_mem_get(thread_key_mctx, sizeof(*mem)); if (mem == NULL) return (ISC_R_NOMEMORY); *mem = proc; - if (isc_key_setspecific(totext_filter_proc_key, mem) != 0) + if (isc_thread_key_setspecific(totext_filter_proc_key, mem) != 0) { + isc_mem_put(thread_key_mctx, mem, sizeof(*mem)); result = ISC_R_UNEXPECTED; + } return (result); #else totext_filter_proc = proc; @@ -2350,3 +2394,19 @@ dns_name_copy(dns_name_t *source, dns_name_t *dest, isc_buffer_t *target) { return (ISC_R_SUCCESS); } +void +dns_name_destroy(void) { +#ifdef ISC_PLATFORM_USETHREADS + RUNTIME_CHECK(isc_once_do(&once, thread_key_mutex_init) + == ISC_R_SUCCESS); + + LOCK(&thread_key_mutex); + if (thread_key_initialized) { + isc_mem_detach(&thread_key_mctx); + isc_thread_key_delete(totext_filter_proc_key); + thread_key_initialized = 0; + } + UNLOCK(&thread_key_mutex); + +#endif +} diff --git a/lib/isc/pthreads/include/isc/thread.h b/lib/isc/pthreads/include/isc/thread.h index 4fee67831b..32626077f7 100644 --- a/lib/isc/pthreads/include/isc/thread.h +++ b/lib/isc/pthreads/include/isc/thread.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: thread.h,v 1.20.18.3 2005/09/09 06:22:09 marka Exp $ */ +/* $Id: thread.h,v 1.20.18.4 2005/09/18 07:58:08 marka Exp $ */ #ifndef ISC_THREAD_H #define ISC_THREAD_H 1 @@ -50,10 +50,10 @@ isc_thread_setconcurrency(unsigned int level); #define isc_thread_self \ (unsigned long)pthread_self -#define isc_key_create pthread_key_create -#define isc_key_getspecific pthread_getspecific -#define isc_key_setspecific pthread_setspecific -#define isc_key_delete pthread_key_delete +#define isc_thread_key_create pthread_key_create +#define isc_thread_key_getspecific pthread_getspecific +#define isc_thread_key_setspecific pthread_setspecific +#define isc_thread_key_delete pthread_key_delete ISC_LANG_ENDDECLS diff --git a/lib/isc/win32/include/isc/thread.h b/lib/isc/win32/include/isc/thread.h index c8bbab9e3f..e993caf27c 100644 --- a/lib/isc/win32/include/isc/thread.h +++ b/lib/isc/win32/include/isc/thread.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: thread.h,v 1.16.18.2 2005/09/09 14:11:05 marka Exp $ */ +/* $Id: thread.h,v 1.16.18.3 2005/09/18 07:58:09 marka Exp $ */ #ifndef ISC_THREAD_H #define ISC_THREAD_H 1 @@ -68,7 +68,7 @@ typedef HANDLE isc_thread_t; typedef unsigned int isc_threadresult_t; typedef void * isc_threadarg_t; typedef isc_threadresult_t (WINAPI *isc_threadfunc_t)(isc_threadarg_t); -typedef DWORD isc_thread_key_t; +typedef DWORD isc_thread_key_t; #define isc_thread_self (unsigned long)GetCurrentThreadId @@ -83,18 +83,18 @@ isc_thread_join(isc_thread_t, isc_threadresult_t *); void isc_thread_setconcurrency(unsigned int level); -int -isc_key_create(isc_thread_key_t *key, void (*func)(void *)); - -int -isc_key_destroy(isc_thread_key_t key); - -void * -isc_key_getspecific(isc_thread_key); - -int -isc_key_setspecific(isc_thread_key_t key, void *value); - +int +isc_thread_key_create(isc_thread_key_t *key, void (*func)(void *)); + +int +isc_thread_key_destroy(isc_thread_key_t key); + +void * +isc_thread_key_getspecific(isc_thread_key); + +int +isc_thread_key_setspecific(isc_thread_key_t key, void *value); + ISC_LANG_ENDDECLS #endif /* ISC_THREAD_H */ diff --git a/lib/isc/win32/thread.c b/lib/isc/win32/thread.c index d20dccf20e..65c10e118a 100644 --- a/lib/isc/win32/thread.c +++ b/lib/isc/win32/thread.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: thread.c,v 1.18.18.3 2005/09/12 07:10:41 marka Exp $ */ +/* $Id: thread.c,v 1.18.18.4 2005/09/18 07:58:08 marka Exp $ */ #include @@ -88,4 +88,3 @@ int isc_key_destroy(isc_thread_key_t key) { return (TlsFree(key) ? 0 : GetLastError()); } -