]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Use library constructor/destructor to initialize OpenSSL
authorOndřej Surý <ondrej@sury.org>
Tue, 9 Feb 2021 16:44:40 +0000 (17:44 +0100)
committerOndřej Surý <ondrej@isc.org>
Fri, 26 Feb 2021 16:18:06 +0000 (17:18 +0100)
Instead of calling isc_tls_initialize()/isc_tls_destroy() explicitly use
gcc/clang attributes on POSIX and DLLMain on Windows to initialize and
shutdown OpenSSL library.

This resolves the issue when isc_nm_create() / isc_nm_destroy() was
called multiple times and it would call OpenSSL library destructors from
isc_nm_destroy().

At the same time, since we now have introduced the ctor/dtor for libisc,
this commit moves the isc_mem API initialization (the list of the
contexts) and changes the isc_mem_checkdestroyed() to schedule the
checking of memory context on library unload instead of executing the
code immediately.

19 files changed:
aclocal.m4
config.h.in
configure
configure.ac
lib/dns/openssl_link.c
lib/isc/include/isc/tls.h
lib/isc/include/isc/util.h
lib/isc/lib.c
lib/isc/mem.c
lib/isc/mem_p.h
lib/isc/netmgr/netmgr.c
lib/isc/netmgr/tlsdns.c
lib/isc/tests/tlsdns_test.c
lib/isc/tls.c
lib/isc/tls_p.h [new file with mode: 0644]
lib/isc/win32/DLLMain.c
lib/isc/win32/libisc.def.in
m4/ax_gcc_func_attribute.m4 [new file with mode: 0644]
util/copyrights

index afaa95a961c760e3c5ce8c3461da05a184e87b4e..6977695510b07bc6ae08abc51db19acb0e9bc8f2 100644 (file)
@@ -376,6 +376,7 @@ AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)])
 
 m4_include([m4/ax_check_compile_flag.m4])
 m4_include([m4/ax_check_openssl.m4])
+m4_include([m4/ax_gcc_func_attribute.m4])
 m4_include([m4/ax_posix_shell.m4])
 m4_include([m4/ax_pthread.m4])
 m4_include([m4/ax_restore_flags.m4])
index b77310c09975b14a1255a4871c734a286c07e586..350f98dd310f3090e460b9f006e4a686bebf7a8f 100644 (file)
 /* Define to 1 if fseeko (and presumably ftello) exists and is declared. */
 #undef HAVE_FSEEKO
 
+/* Define to 1 if the system has the `constructor' function attribute */
+#undef HAVE_FUNC_ATTRIBUTE_CONSTRUCTOR
+
+/* Define to 1 if the system has the `destructor' function attribute */
+#undef HAVE_FUNC_ATTRIBUTE_DESTRUCTOR
+
 /* Build with GeoIP2 support */
 #undef HAVE_GEOIP2
 
index de175bd4f2360f888dde487fdf86bdee15458a07..205c2ee0df07091d31950f559a711a3a6b494a59 100755 (executable)
--- a/configure
+++ b/configure
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking contributed DLZ drivers" >&5
 $as_echo_n "checking contributed DLZ drivers... " >&6; }
 
+#
+# Support for constructor and destructor attributes
+#
+
+
+
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for __attribute__((constructor))" >&5
+$as_echo_n "checking for __attribute__((constructor))... " >&6; }
+if ${ax_cv_have_func_attribute_constructor+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+        cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+
+                    int foo( void ) __attribute__((constructor));
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+                                      if test -s conftest.err; then :
+  ax_cv_have_func_attribute_constructor=no
+else
+  ax_cv_have_func_attribute_constructor=yes
+fi
+else
+  ax_cv_have_func_attribute_constructor=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_have_func_attribute_constructor" >&5
+$as_echo "$ax_cv_have_func_attribute_constructor" >&6; }
+
+    if test yes = $ax_cv_have_func_attribute_constructor; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_FUNC_ATTRIBUTE_CONSTRUCTOR 1
+_ACEOF
+
+fi
+
+
+
+
+
+
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for __attribute__((destructor))" >&5
+$as_echo_n "checking for __attribute__((destructor))... " >&6; }
+if ${ax_cv_have_func_attribute_destructor+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+        cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+
+                    int foo( void ) __attribute__((destructor));
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+                                      if test -s conftest.err; then :
+  ax_cv_have_func_attribute_destructor=no
+else
+  ax_cv_have_func_attribute_destructor=yes
+fi
+else
+  ax_cv_have_func_attribute_destructor=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_have_func_attribute_destructor" >&5
+$as_echo "$ax_cv_have_func_attribute_destructor" >&6; }
+
+    if test yes = $ax_cv_have_func_attribute_destructor; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_FUNC_ATTRIBUTE_DESTRUCTOR 1
+_ACEOF
+
+fi
+
+
+
+
 if test -n "$CONTRIB_DLZ"
 then
        { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
index 242287cf00f4fbce1f3e081cd0ca311d9fd558cb..f5483fec0d2b2e7ef4af586a5584c424bf020a93 100644 (file)
@@ -2628,6 +2628,12 @@ AS_IF([test "$enable_dnsrps" != "no"],[
 sinclude(contrib/dlz/config.dlz.in)
 AC_MSG_CHECKING(contributed DLZ drivers)
 
+#
+# Support for constructor and destructor attributes
+#
+AX_GCC_FUNC_ATTRIBUTE([constructor])
+AX_GCC_FUNC_ATTRIBUTE([destructor])
+
 if test -n "$CONTRIB_DLZ"
 then
        AC_MSG_RESULT(yes)
index bb26adcf26dffd5069ade9d24f2246c3ac60d6aa..1060fcc4ff99dacd5af664c6edb39665d0da55de 100644 (file)
@@ -68,8 +68,6 @@ isc_result_t
 dst__openssl_init(const char *engine) {
        isc_result_t result = ISC_R_SUCCESS;
 
-       isc_tls_initialize();
-
        enable_fips_mode();
 
 #if !defined(OPENSSL_NO_ENGINE)
@@ -110,7 +108,6 @@ dst__openssl_destroy(void) {
        }
        e = NULL;
 #endif /* if !defined(OPENSSL_NO_ENGINE) */
-       isc_tls_destroy();
 }
 
 static isc_result_t
index d0318262e5f02c00341bbfae0f4f9e0a844f1121..3741f19f5efadf22d0a7940c4b40f7d53fe11ea1 100644 (file)
 
 typedef struct ssl_ctx_st isc_tlsctx_t;
 
-void
-isc_tls_initialize(void);
-
-void
-isc_tls_destroy(void);
-
 void
 isc_tlsctx_free(isc_tlsctx_t **ctpx);
 /*%
index 8941ec125e03c19918a6dc8df7ad369ad642d649..3c8c40b67914b204f9b3f893c39be52def53cf21 100644 (file)
 #define ISC_NONSTRING
 #endif /* __GNUC__ */
 
+#if HAVE_FUNC_ATTRIBUTE_CONSTRUCTOR && HAVE_FUNC_ATTRIBUTE_DESTRUCTOR
+#define ISC_CONSTRUCTOR(priority) __attribute__((constructor(priority)))
+#define ISC_DESTRUCTOR(priority)  __attribute__((destructor(priority)))
+#elif WIN32
+#define ISC_CONSTRUCTOR(priority)
+#define ISC_DESTRUCTOR(priority)
+#else
+#error Either __attribute__((constructor|destructor))__ or DllMain support needed to compile BIND 9.
+#endif
+
 /*%
  * The opposite: silent warnings about stored values which are never read.
  */
index 8bee4c21a4988e5e8313dfe3242450dda18c5ff9..dad744903dd06d184de295c317a57e842eb50839 100644 (file)
 
 #include <isc/bind9.h>
 #include <isc/lib.h>
+#include <isc/mem.h>
+#include <isc/tls.h>
+#include <isc/util.h>
+
+#include "mem_p.h"
+#include "tls_p.h"
 
 /***
  *** Functions
@@ -22,3 +28,20 @@ void
 isc_lib_register(void) {
        isc_bind9 = false;
 }
+
+void
+isc__initialize(void) ISC_CONSTRUCTOR(101);
+void
+isc__shutdown(void) ISC_DESTRUCTOR(101);
+
+void
+isc__initialize(void) {
+       isc__mem_initialize();
+       isc__tls_initialize();
+}
+
+void
+isc__shutdown(void) {
+       isc__tls_shutdown();
+       isc__mem_shutdown();
+}
index 71894af09c9155776ebadb88782c6f66806f8b57..e9156994d2b447b5fc9862f0a03a7fc321708e37 100644 (file)
@@ -117,7 +117,8 @@ struct stats {
 
 static ISC_LIST(isc__mem_t) contexts;
 
-static isc_once_t once = ISC_ONCE_INIT;
+static isc_once_t init_once = ISC_ONCE_INIT;
+static isc_once_t shut_once = ISC_ONCE_INIT;
 static isc_mutex_t contextslock;
 
 /*%
@@ -743,12 +744,29 @@ default_memfree(void *ptr) {
 }
 
 static void
-initialize_action(void) {
+mem_initialize(void) {
        isc_mutex_init(&contextslock);
        ISC_LIST_INIT(contexts);
        totallost = 0;
 }
 
+void
+isc__mem_initialize(void) {
+       RUNTIME_CHECK(isc_once_do(&init_once, mem_initialize) == ISC_R_SUCCESS);
+}
+
+static void
+mem_shutdown(void) {
+       isc__mem_checkdestroyed();
+
+       isc_mutex_destroy(&contextslock);
+}
+
+void
+isc__mem_shutdown(void) {
+       RUNTIME_CHECK(isc_once_do(&shut_once, mem_shutdown) == ISC_R_SUCCESS);
+}
+
 static void
 mem_create(isc_mem_t **ctxp, unsigned int flags) {
        REQUIRE(ctxp != NULL && *ctxp == NULL);
@@ -758,8 +776,6 @@ mem_create(isc_mem_t **ctxp, unsigned int flags) {
        STATIC_ASSERT((ALIGNMENT_SIZE & (ALIGNMENT_SIZE - 1)) == 0,
                      "wrong alignment size");
 
-       RUNTIME_CHECK(isc_once_do(&once, initialize_action) == ISC_R_SUCCESS);
-
        ctx = (default_memalloc)(sizeof(*ctx));
 
        isc_mutex_init(&ctx->lock);
@@ -2049,13 +2065,20 @@ print_contexts(FILE *file) {
        fflush(file);
 }
 
+static atomic_uintptr_t checkdestroyed = ATOMIC_VAR_INIT(0);
+
 void
 isc_mem_checkdestroyed(FILE *file) {
-#if !ISC_MEM_TRACKLINES
-       UNUSED(file);
-#endif /* if !ISC_MEM_TRACKLINES */
+       atomic_store_release(&checkdestroyed, (uintptr_t)file);
+}
 
-       RUNTIME_CHECK(isc_once_do(&once, initialize_action) == ISC_R_SUCCESS);
+void
+isc__mem_checkdestroyed(void) {
+       FILE *file = (FILE *)atomic_load_acquire(&checkdestroyed);
+
+       if (file == NULL) {
+               return;
+       }
 
        LOCK(&contextslock);
        if (!ISC_LIST_EMPTY(contexts)) {
@@ -2205,8 +2228,6 @@ isc_mem_renderxml(void *writer0) {
 
        TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "contexts"));
 
-       RUNTIME_CHECK(isc_once_do(&once, initialize_action) == ISC_R_SUCCESS);
-
        LOCK(&contextslock);
        lost = totallost;
        for (ctx = ISC_LIST_HEAD(contexts); ctx != NULL;
@@ -2368,7 +2389,6 @@ isc_mem_renderjson(void *memobj0) {
        json_object *memobj = (json_object *)memobj0;
 
        memset(&summary, 0, sizeof(summary));
-       RUNTIME_CHECK(isc_once_do(&once, initialize_action) == ISC_R_SUCCESS);
 
        ctxarray = json_object_new_array();
        CHECKMEM(ctxarray);
index f1889c668b2df96f96fe7497d79c1661dc53ade2..dc17e06420f2c41d33c16eeca61abaf7cad404df 100644 (file)
@@ -9,8 +9,11 @@
  * information regarding copyright ownership.
  */
 
-#ifndef ISC_MEM_P_H
-#define ISC_MEM_P_H
+#pragma once
+
+#include <stdio.h>
+
+#include <isc/mem.h>
 
 /*! \file */
 
@@ -21,4 +24,11 @@ isc__mem_printactive(isc_mem_t *mctx, FILE *file);
  * a single memory context.
  */
 
-#endif /* ISC_MEM_P_H */
+void
+isc__mem_checkdestroyed(void);
+
+void
+isc__mem_initialize(void);
+
+void
+isc__mem_shutdown(void);
index db467318019c36e44420ec7332055bfa26f73178..be365db8639d05a18a670d75ce8d01fe5d40d886 100644 (file)
@@ -216,8 +216,6 @@ isc_nm_start(isc_mem_t *mctx, uint32_t workers) {
        isc__nm_winsock_initialize();
 #endif /* WIN32 */
 
-       isc_tls_initialize();
-
        mgr = isc_mem_get(mctx, sizeof(*mgr));
        *mgr = (isc_nm_t){ .nworkers = workers };
 
@@ -374,8 +372,6 @@ nm_destroy(isc_nm_t **mgr0) {
                    mgr->nworkers * sizeof(isc__networker_t));
        isc_mem_putanddetach(&mgr->mctx, mgr, sizeof(*mgr));
 
-       isc_tls_destroy();
-
 #ifdef WIN32
        isc__nm_winsock_destroy();
 #endif /* WIN32 */
index 90aa605232b08033c1c2ad4e6fedac665d86fe4f..eaa8921b150acf265d220106cb9d012b0345bb1d 100644 (file)
@@ -398,6 +398,7 @@ isc_nm_tlsdnsconnect(isc_nm_t *mgr, isc_nmiface_t *local, isc_nmiface_t *peer,
        REQUIRE(VALID_NM(mgr));
        REQUIRE(local != NULL);
        REQUIRE(peer != NULL);
+       REQUIRE(sslctx != NULL);
 
        sa_family = peer->addr.type.sa.sa_family;
 
@@ -1656,6 +1657,16 @@ accept_connection(isc_nmsocket_t *ssock, isc_quota_t *quota) {
        csock->tls.state = TLS_STATE_NONE;
 
        csock->tls.ssl = SSL_new(ssock->tls.ctx);
+
+       if (csock->tls.ssl == NULL) {
+               char errbuf[256];
+               unsigned long err = ERR_get_error();
+
+               ERR_error_string_n(err, errbuf, sizeof(errbuf));
+               fprintf(stderr, "%s:SSL_new(%p) -> %s\n", __func__,
+                       ssock->tls.ctx, errbuf);
+       }
+
        RUNTIME_CHECK(csock->tls.ssl != NULL);
 
        r = BIO_new_bio_pair(&csock->tls.ssl_wbio, TLS_BUF_SIZE,
index 778f08f31ee264145b2c4601e9c44b3d161ad0cb..7eadb4a781e32403c9f70faeb1cf3438724b316c 100644 (file)
@@ -214,8 +214,13 @@ nm_setup(void **state) {
        int tlsdns_listen_sock = -1;
        isc_nm_t **nm = NULL;
 
-       isc_tlsctx_createserver(NULL, NULL, &tlsdns_listen_ctx);
-       isc_tlsctx_createclient(&tlsdns_connect_ctx);
+       if (isc_tlsctx_createserver(NULL, NULL, &tlsdns_listen_ctx) !=
+           ISC_R_SUCCESS) {
+               return (-1);
+       }
+       if (isc_tlsctx_createclient(&tlsdns_connect_ctx) != ISC_R_SUCCESS) {
+               return (-1);
+       }
 
        tlsdns_listen_addr = (isc_sockaddr_t){ .length = 0 };
        tlsdns_listen_sock = setup_ephemeral_port(&tlsdns_listen_addr,
index d3238b5b7fb6038566bc4216672547a0a9bdadd3..b234b3a9e0ef2089ca9b073aa8db26ad6ec9e14d 100644 (file)
 #include <isc/util.h>
 
 #include "openssl_shim.h"
+#include "tls_p.h"
 
 static isc_once_t init_once = ISC_ONCE_INIT;
 static isc_once_t shut_once = ISC_ONCE_INIT;
 static atomic_bool init_done = ATOMIC_VAR_INIT(false);
 static atomic_bool shut_done = ATOMIC_VAR_INIT(false);
-static isc_mem_t *isc__tls_mctx = NULL;
 
 #if OPENSSL_VERSION_NUMBER < 0x10100000L
 static isc_mutex_t *locks = NULL;
@@ -52,53 +52,30 @@ isc__tls_set_thread_id(CRYPTO_THREADID *id) {
 }
 #endif
 
-#if 0
-static void *
-isc__tls_malloc(size_t size, const char *file, int line) {
-       UNUSED(file);
-       UNUSED(line);
-
-       return (isc_mem_allocate(isc__tls_mctx, size));
-}
-
-static void *
-isc__tls_realloc(void *ptr, size_t size, const char *file, int line) {
-       UNUSED(file);
-       UNUSED(line);
-
-       return (isc__mem_reallocate(isc__tls_mctx, ptr, size));
-}
-
-static void
-isc__tls_free(void *ptr, const char *file, int line) {
-       UNUSED(file);
-       UNUSED(line);
-
-       if (ptr == NULL) {
-               return;
-       }
-
-       isc__mem_free(isc__tls_mctx, ptr);
-}
-#endif
-
 static void
-isc__tls_initialize(void) {
+tls_initialize(void) {
        REQUIRE(!atomic_load(&init_done));
 
-       isc_mem_create(&isc__tls_mctx);
-       /* isc_mem_setdestroycheck(isc__tls_mctx, false); */
-
-       /* REQUIRE(CRYPTO_set_mem_functions(isc__tls_malloc, isc__tls_realloc,
-        * isc__tls_free) == 1); */
-
 #if OPENSSL_VERSION_NUMBER >= 0x10100000L
        RUNTIME_CHECK(OPENSSL_init_ssl(OPENSSL_INIT_ENGINE_ALL_BUILTIN |
                                               OPENSSL_INIT_LOAD_CONFIG,
                                       NULL) == 1);
 #else
        nlocks = CRYPTO_num_locks();
-       locks = isc_mem_get(isc__tls_mctx, nlocks * sizeof(locks[0]));
+       /*
+        * We can't use isc_mem API here, because it's called too
+        * early and when the isc_mem_debugging flags are changed
+        * later and ISC_MEM_DEBUGSIZE or ISC_MEM_DEBUGCTX flags are
+        * added, neither isc_mem_put() nor isc_mem_free() can be used
+        * to free up the memory allocated here because the flags were
+        * not set when calling isc_mem_get() or isc_mem_allocate()
+        * here.
+        *
+        * Actually, since this is a single allocation at library load
+        * and deallocation at library unload, using the standard
+        * allocator without the tracking is fine for this purpose.
+        */
+       locks = calloc(nlocks, sizeof(locks[0]));
        isc_mutexblock_init(locks, nlocks);
        CRYPTO_set_locking_callback(isc__tls_lock_callback);
        CRYPTO_THREADID_set_callback(isc__tls_set_thread_id);
@@ -127,20 +104,22 @@ isc__tls_initialize(void) {
                            "seeded' message in the OpenSSL FAQ)");
        }
 
-       atomic_compare_exchange_strong(&init_done, &(bool){ false }, true);
+       REQUIRE(atomic_compare_exchange_strong(&init_done, &(bool){ false },
+                                              true));
 }
 
 void
-isc_tls_initialize(void) {
-       isc_result_t result = isc_once_do(&init_once, isc__tls_initialize);
+isc__tls_initialize(void) {
+       isc_result_t result = isc_once_do(&init_once, tls_initialize);
        REQUIRE(result == ISC_R_SUCCESS);
        REQUIRE(atomic_load(&init_done));
 }
 
 static void
-isc__tls_destroy(void) {
+tls_shutdown(void) {
        REQUIRE(atomic_load(&init_done));
        REQUIRE(!atomic_load(&shut_done));
+
 #if OPENSSL_VERSION_NUMBER < 0x10100000L
 
        CONF_modules_unload(1);
@@ -156,24 +135,20 @@ isc__tls_destroy(void) {
 
        CRYPTO_set_locking_callback(NULL);
 
-       /* REQUIRE(CRYPTO_set_mem_functions(OPENSSL_malloc, OPENSSL_realloc,
-        * OPENSSL_free) == 1); */
-
        if (locks != NULL) {
-               INSIST(isc__tls_mctx != NULL);
                isc_mutexblock_destroy(locks, nlocks);
-               isc_mem_put(isc__tls_mctx, locks, nlocks * sizeof(locks[0]));
+               free(locks);
                locks = NULL;
        }
 #endif
-       isc_mem_detach(&isc__tls_mctx);
 
-       atomic_compare_exchange_strong(&shut_done, &(bool){ false }, true);
+       REQUIRE(atomic_compare_exchange_strong(&shut_done, &(bool){ false },
+                                              true));
 }
 
 void
-isc_tls_destroy(void) {
-       isc_result_t result = isc_once_do(&shut_once, isc__tls_destroy);
+isc__tls_shutdown(void) {
+       isc_result_t result = isc_once_do(&shut_once, tls_shutdown);
        REQUIRE(result == ISC_R_SUCCESS);
        REQUIRE(atomic_load(&shut_done));
 }
@@ -198,8 +173,6 @@ isc_tlsctx_createclient(isc_tlsctx_t **ctxp) {
 
        REQUIRE(ctxp != NULL && *ctxp == NULL);
 
-       isc_tls_initialize();
-
        method = TLS_client_method();
        if (method == NULL) {
                goto ssl_error;
@@ -246,8 +219,6 @@ isc_tlsctx_createserver(const char *keyfile, const char *certfile,
 
        REQUIRE(ctxp != NULL && *ctxp == NULL);
 
-       isc_tls_initialize();
-
        if (ephemeral) {
                INSIST(keyfile == NULL);
                INSIST(certfile == NULL);
@@ -363,6 +334,7 @@ ssl_error:
        isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL, ISC_LOGMODULE_NETMGR,
                      ISC_LOG_ERROR, "Error initializing TLS context: %s",
                      errbuf);
+
        if (ctx != NULL) {
                SSL_CTX_free(ctx);
        }
diff --git a/lib/isc/tls_p.h b/lib/isc/tls_p.h
new file mode 100644 (file)
index 0000000..5d44c64
--- /dev/null
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#pragma once
+
+void
+isc__tls_initialize(void);
+
+void
+isc__tls_shutdown(void);
index 3acfee4f4679e9ba1e45776634865742a8992e02..c649effbc278f897b7e7bed05abdc6efccf93260 100644 (file)
 #include <stdio.h>
 #include <windows.h>
 
+#include <isc/mem.h>
+#include <isc/tls.h>
+#include <isc/util.h>
+
+#include "mem_p.h"
+#include "tls_p.h"
+
 /*
  * Called when we enter the DLL
  */
@@ -27,6 +34,8 @@ __declspec(dllexport) BOOL WINAPI
                 * Disable DllMain() invocation on Thread creation/destruction
                 */
                DisableThreadLibraryCalls(hinstDLL);
+               isc__mem_initialize();
+               isc__tls_initialize();
                break;
 
        /*
@@ -34,6 +43,8 @@ __declspec(dllexport) BOOL WINAPI
         * termination or a call to FreeLibrary.
         */
        case DLL_PROCESS_DETACH:
+               isc__tls_shutdown();
+               isc__mem_shutdown();
                break;
 
        case DLL_THREAD_ATTACH:
@@ -43,6 +54,7 @@ __declspec(dllexport) BOOL WINAPI
                 * disabled.
                 */
                INSIST(0);
+               ISC_UNREACHABLE();
                break;
 
        default:
index cadbf8eb19cc6e6250679af78188143e1cb413ca..c3631bf308eb8b61360310950eabcf53c4f7b59d 100644 (file)
@@ -372,6 +372,9 @@ isc_md_get_block_size
 isc_md_type_get_size
 isc_md_type_get_block_size
 isc_md
+isc__mem_checkdestroyed
+isc__mem_initialize
+isc__mem_shutdown
 isc_mem_attach
 isc_mem_checkdestroyed
 isc_mem_create
@@ -709,8 +712,8 @@ isc_timermgr_create
 isc_timermgr_createinctx
 isc_timermgr_destroy
 isc_timermgr_poke
-isc_tls_initialize
-isc_tls_destroy
+isc__tls_initialize
+isc__tls_shutdown
 isc_tlsctx_createclient
 isc_tlsctx_createserver
 isc_tlsctx_free
diff --git a/m4/ax_gcc_func_attribute.m4 b/m4/ax_gcc_func_attribute.m4
new file mode 100644 (file)
index 0000000..c926439
--- /dev/null
@@ -0,0 +1,242 @@
+# ===========================================================================
+#  https://www.gnu.org/software/autoconf-archive/ax_gcc_func_attribute.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+#   AX_GCC_FUNC_ATTRIBUTE(ATTRIBUTE)
+#
+# DESCRIPTION
+#
+#   This macro checks if the compiler supports one of GCC's function
+#   attributes; many other compilers also provide function attributes with
+#   the same syntax. Compiler warnings are used to detect supported
+#   attributes as unsupported ones are ignored by default so quieting
+#   warnings when using this macro will yield false positives.
+#
+#   The ATTRIBUTE parameter holds the name of the attribute to be checked.
+#
+#   If ATTRIBUTE is supported define HAVE_FUNC_ATTRIBUTE_<ATTRIBUTE>.
+#
+#   The macro caches its result in the ax_cv_have_func_attribute_<attribute>
+#   variable.
+#
+#   The macro currently supports the following function attributes:
+#
+#    alias
+#    aligned
+#    alloc_size
+#    always_inline
+#    artificial
+#    cold
+#    const
+#    constructor
+#    constructor_priority for constructor attribute with priority
+#    deprecated
+#    destructor
+#    dllexport
+#    dllimport
+#    error
+#    externally_visible
+#    fallthrough
+#    flatten
+#    format
+#    format_arg
+#    gnu_format
+#    gnu_inline
+#    hot
+#    ifunc
+#    leaf
+#    malloc
+#    noclone
+#    noinline
+#    nonnull
+#    noreturn
+#    nothrow
+#    optimize
+#    pure
+#    sentinel
+#    sentinel_position
+#    unused
+#    used
+#    visibility
+#    warning
+#    warn_unused_result
+#    weak
+#    weakref
+#
+#   Unsupported function attributes will be tested with a prototype
+#   returning an int and not accepting any arguments and the result of the
+#   check might be wrong or meaningless so use with care.
+#
+# LICENSE
+#
+#   Copyright (c) 2013 Gabriele Svelto <gabriele.svelto@gmail.com>
+#
+#   Copying and distribution of this file, with or without modification, are
+#   permitted in any medium without royalty provided the copyright notice
+#   and this notice are preserved.  This file is offered as-is, without any
+#   warranty.
+
+#serial 10
+
+AC_DEFUN([AX_GCC_FUNC_ATTRIBUTE], [
+    AS_VAR_PUSHDEF([ac_var], [ax_cv_have_func_attribute_$1])
+
+    AC_CACHE_CHECK([for __attribute__(($1))], [ac_var], [
+        AC_LINK_IFELSE([AC_LANG_PROGRAM([
+            m4_case([$1],
+                [alias], [
+                    int foo( void ) { return 0; }
+                    int bar( void ) __attribute__(($1("foo")));
+                ],
+                [aligned], [
+                    int foo( void ) __attribute__(($1(32)));
+                ],
+                [alloc_size], [
+                    void *foo(int a) __attribute__(($1(1)));
+                ],
+                [always_inline], [
+                    inline __attribute__(($1)) int foo( void ) { return 0; }
+                ],
+                [artificial], [
+                    inline __attribute__(($1)) int foo( void ) { return 0; }
+                ],
+                [cold], [
+                    int foo( void ) __attribute__(($1));
+                ],
+                [const], [
+                    int foo( void ) __attribute__(($1));
+                ],
+                [constructor_priority], [
+                    int foo( void ) __attribute__((__constructor__(65535/2)));
+                ],
+                [constructor], [
+                    int foo( void ) __attribute__(($1));
+                ],
+                [deprecated], [
+                    int foo( void ) __attribute__(($1("")));
+                ],
+                [destructor], [
+                    int foo( void ) __attribute__(($1));
+                ],
+                [dllexport], [
+                    __attribute__(($1)) int foo( void ) { return 0; }
+                ],
+                [dllimport], [
+                    int foo( void ) __attribute__(($1));
+                ],
+                [error], [
+                    int foo( void ) __attribute__(($1("")));
+                ],
+                [externally_visible], [
+                    int foo( void ) __attribute__(($1));
+                ],
+                [fallthrough], [
+                    int foo( void ) {switch (0) { case 1: __attribute__(($1)); case 2: break ; }};
+                ],
+                [flatten], [
+                    int foo( void ) __attribute__(($1));
+                ],
+                [format], [
+                    int foo(const char *p, ...) __attribute__(($1(printf, 1, 2)));
+                ],
+                [gnu_format], [
+                    int foo(const char *p, ...) __attribute__((format(gnu_printf, 1, 2)));
+                ],
+                [format_arg], [
+                    char *foo(const char *p) __attribute__(($1(1)));
+                ],
+                [gnu_inline], [
+                    inline __attribute__(($1)) int foo( void ) { return 0; }
+                ],
+                [hot], [
+                    int foo( void ) __attribute__(($1));
+                ],
+                [ifunc], [
+                    int my_foo( void ) { return 0; }
+                    static int (*resolve_foo(void))(void) { return my_foo; }
+                    int foo( void ) __attribute__(($1("resolve_foo")));
+                ],
+                [leaf], [
+                    __attribute__(($1)) int foo( void ) { return 0; }
+                ],
+                [malloc], [
+                    void *foo( void ) __attribute__(($1));
+                ],
+                [noclone], [
+                    int foo( void ) __attribute__(($1));
+                ],
+                [noinline], [
+                    __attribute__(($1)) int foo( void ) { return 0; }
+                ],
+                [nonnull], [
+                    int foo(char *p) __attribute__(($1(1)));
+                ],
+                [noreturn], [
+                    void foo( void ) __attribute__(($1));
+                ],
+                [nothrow], [
+                    int foo( void ) __attribute__(($1));
+                ],
+                [optimize], [
+                    __attribute__(($1(3))) int foo( void ) { return 0; }
+                ],
+                [pure], [
+                    int foo( void ) __attribute__(($1));
+                ],
+                [sentinel], [
+                    int foo(void *p, ...) __attribute__(($1));
+                ],
+                [sentinel_position], [
+                    int foo(void *p, ...) __attribute__(($1(1)));
+                ],
+                [returns_nonnull], [
+                    void *foo( void ) __attribute__(($1));
+                ],
+                [unused], [
+                    int foo( void ) __attribute__(($1));
+                ],
+                [used], [
+                    int foo( void ) __attribute__(($1));
+                ],
+                [visibility], [
+                    int foo_def( void ) __attribute__(($1("default")));
+                    int foo_hid( void ) __attribute__(($1("hidden")));
+                    int foo_int( void ) __attribute__(($1("internal")));
+                    int foo_pro( void ) __attribute__(($1("protected")));
+                ],
+                [warning], [
+                    int foo( void ) __attribute__(($1("")));
+                ],
+                [warn_unused_result], [
+                    int foo( void ) __attribute__(($1));
+                ],
+                [weak], [
+                    int foo( void ) __attribute__(($1));
+                ],
+                [weakref], [
+                    static int foo( void ) { return 0; }
+                    static int bar( void ) __attribute__(($1("foo")));
+                ],
+                [
+                 m4_warn([syntax], [Unsupported attribute $1, the test may fail])
+                 int foo( void ) __attribute__(($1));
+                ]
+            )], [])
+            ],
+            dnl GCC doesn't exit with an error if an unknown attribute is
+            dnl provided but only outputs a warning, so accept the attribute
+            dnl only if no warning were issued.
+            [AS_IF([test -s conftest.err],
+                [AS_VAR_SET([ac_var], [no])],
+                [AS_VAR_SET([ac_var], [yes])])],
+            [AS_VAR_SET([ac_var], [no])])
+    ])
+
+    AS_IF([test yes = AS_VAR_GET([ac_var])],
+        [AC_DEFINE_UNQUOTED(AS_TR_CPP(HAVE_FUNC_ATTRIBUTE_$1), 1,
+            [Define to 1 if the system has the `$1' function attribute])], [])
+
+    AS_VAR_POPDEF([ac_var])
+])
index feb15472ca66b91f4d9a77279b6322fd6a8eee67..d5260916e16150379f6e98bacedb3c5bc0482ade 100644 (file)
 ./lib/isc/timer.c                              C       1998,1999,2000,2001,2002,2004,2005,2007,2008,2009,2011,2012,2013,2014,2015,2016,2017,2018,2019,2020,2021
 ./lib/isc/timer_p.h                            C       2000,2001,2004,2005,2007,2009,2016,2017,2018,2019,2020,2021
 ./lib/isc/tls.c                                        C       2021
+./lib/isc/tls_p.h                              C       2021
 ./lib/isc/tm.c                                 C       2014,2016,2018,2019,2020,2021
 ./lib/isc/unix/dir.c                           C       1999,2000,2001,2004,2005,2007,2008,2009,2011,2012,2016,2017,2018,2019,2020,2021
 ./lib/isc/unix/errno.c                         C       2016,2018,2019,2020,2021