]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
finetune isc_thread_key implementation [RT #15408]
authorMark Andrews <marka@isc.org>
Sun, 18 Sep 2005 07:58:09 +0000 (07:58 +0000)
committerMark Andrews <marka@isc.org>
Sun, 18 Sep 2005 07:58:09 +0000 (07:58 +0000)
13 files changed:
bin/check/named-checkconf.c
bin/check/named-checkzone.c
bin/dig/dighost.c
bin/dnssec/dnssec-keygen.c
bin/dnssec/dnssec-signzone.c
bin/named/main.c
bin/nsupdate/nsupdate.c
bin/rndc/rndc.c
lib/dns/include/dns/name.h
lib/dns/name.c
lib/isc/pthreads/include/isc/thread.h
lib/isc/win32/include/isc/thread.h
lib/isc/win32/thread.c

index e87d4a1457aef273e570e096f6cadd8e1fa814fb..9e5985463836389fc9a410b29e93299c9150ed00 100644 (file)
@@ -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();
index 4a56167e5a2f1029d30f2edbeb980ba6f2c28bb7..0dfcbb06dce53a58059e9dc51f4404f0371e7d04 100644 (file)
@@ -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 */
index 86b331e68a21f909fbfc1b83beb0ed6033cfd797..e7accc1542f04e2a3344bb6b79dadeefc385e4af 100644 (file)
@@ -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);
index 8518749278a3accfb7bd794adaa0a45d223f7c3c..0bfcd53d4a1b8bac0f117cbe62a6decf47d53dd8 100644 (file)
@@ -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);
index f763929691be44c597329405e576f4329a884812..0e23d575f498482de60942e5927466c2e44e04f4 100644 (file)
@@ -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);
index d24f82b421e47ddcb75aa2ad0b2cb95ce0a1b7f2..a217ce356549faf94514d7f7af55ae7a779bf31b 100644 (file)
@@ -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();
index ccf72d304bee4d16eb3723e423ff4e4bd162edff..f1895f83efc32c6db3013f65a0f5573e68467a6b 100644 (file)
@@ -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);
index 743a8ad5e465da83bf7428c213eb30c2cf74fd31..1181a5af1a92ac8b324c2a9f75182143bd81dfcb 100644 (file)
@@ -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);
 
index 3c6b6549b8b1871ef1d47cc7e786b0fb46ec0a53..a19091091e1fcb751b460c3fd51710d362640db9 100644 (file)
@@ -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
index 8f1eb3460523dd9dd8a929483652a1ad28237878..caeeb37e8baade5f05ee574ca0fd153a5bf2084e 100644 (file)
@@ -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
+}
index 4fee67831bffd0996a7698bc11a7e91ed20e4185..32626077f7e503713ad191a4cc0815e3109af291 100644 (file)
@@ -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
 
index c8bbab9e3fdcaa516fc2c8874d7537c943ece5c1..e993caf27ca7532d624cd38ca596703185c6aa73 100644 (file)
@@ -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;\r
+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\r
-isc_key_create(isc_thread_key_t *key, void (*func)(void *));\r
-\r
-int\r
-isc_key_destroy(isc_thread_key_t key);\r
-\r
-void *\r
-isc_key_getspecific(isc_thread_key);\r
-\r
-int\r
-isc_key_setspecific(isc_thread_key_t key, void *value);\r
-\r
+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 */
index d20dccf20eaae04baca65befdb5dfa68891feccb..65c10e118a57d6b54937421e6513e0370d7a6ce1 100644 (file)
@@ -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 <config.h>
 
@@ -88,4 +88,3 @@ int
 isc_key_destroy(isc_thread_key_t key) {
        return (TlsFree(key) ? 0 : GetLastError());
 }
-