summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorminfrin <minfrin@13f79535-47bb-0310-9956-ffa450edef68>2019-06-23 23:13:03 +0000
committerminfrin <minfrin@13f79535-47bb-0310-9956-ffa450edef68>2019-06-23 23:13:03 +0000
commitc946743e4c77b787f98d9f6b677c2e34dfdbcb39 (patch)
tree65596fc49bb78ebef721f07d19bdc64fab242ff6
parentb04f0aa2a44e31b5cf9dcca714a2f43e71f2b1ad (diff)
downloadlibapr-c946743e4c77b787f98d9f6b677c2e34dfdbcb39.tar.gz
apu_dso_init: Fix pool lifetime and introduce a reference count.
apu_dso_init() can now be called more than once (from multiple modules) and from unrelated pools (usually seen in unit tests). git-svn-id: http://svn.apache.org/repos/asf/apr/apr/trunk@1861957 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r--CHANGES5
-rw-r--r--util-misc/apu_dso.c48
2 files changed, 37 insertions, 16 deletions
diff --git a/CHANGES b/CHANGES
index daf0de991..90fa1840b 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,6 +1,11 @@
-*- coding: utf-8 -*-
Changes for APR 2.0.0
+ *) apu_dso_init: Fix pool lifetime and introduce a reference count.
+ apu_dso_init() can now be called more than once (from multiple
+ modules) and from unrelated pools (usually seen in unit tests).
+ [Graham Leggett]
+
*) apr_crypto_openssl: use OPENSSL_init_crypto() to initialise OpenSSL
on versions 1.1+. [Graham Leggett]
diff --git a/util-misc/apu_dso.c b/util-misc/apu_dso.c
index 83ab33eca..060d9afe0 100644
--- a/util-misc/apu_dso.c
+++ b/util-misc/apu_dso.c
@@ -37,7 +37,7 @@
static apr_thread_mutex_t* mutex = NULL;
#endif
static apr_hash_t *dsos = NULL;
-static apr_uint32_t initialised = 0, in_init = 1;
+static apr_uint32_t in_init = 0, initialised = 0;
#if APR_HAS_THREADS
apr_status_t apu_dso_mutex_lock()
@@ -59,11 +59,24 @@ apr_status_t apu_dso_mutex_unlock() {
static apr_status_t apu_dso_term(void *ptr)
{
- /* set statics to NULL so init can work again */
- dsos = NULL;
+ if (apr_atomic_inc32(&in_init)) {
+ while (apr_atomic_read32(&in_init) > 1); /* wait until we get fully inited */
+ }
+
+ /* Reference count - cleanup when last reference is cleaned up */
+ if (!apr_atomic_dec32(&initialised)) {
+ apr_pool_t *global = apr_hash_pool_get(dsos);
+
+ apr_pool_destroy(global);
+
+ /* set statics to NULL so init can work again */
+ dsos = NULL;
#if APR_HAS_THREADS
- mutex = NULL;
+ mutex = NULL;
#endif
+ }
+
+ apr_atomic_dec32(&in_init);
/* Everything else we need is handled by cleanups registered
* when we created mutexes and loaded DSOs
@@ -76,13 +89,22 @@ apr_status_t apu_dso_init(apr_pool_t *pool)
apr_status_t ret = APR_SUCCESS;
apr_pool_t *parent;
- if (apr_atomic_inc32(&initialised)) {
- apr_atomic_set32(&initialised, 1); /* prevent wrap-around */
+ if (apr_atomic_inc32(&in_init)) {
+ while (apr_atomic_read32(&in_init) > 1); /* wait until we get fully inited */
+ }
+
+ /* Reference count increment... */
+ if (!apr_atomic_inc32(&initialised)) {
+ apr_pool_t *global;
+
+ apr_pool_create_unmanaged(&global);
+ dsos = apr_hash_make(global);
- while (apr_atomic_read32(&in_init)) /* wait until we get fully inited */
- ;
+#if APR_HAS_THREADS
+ ret = apr_thread_mutex_create(&mutex, APR_THREAD_MUTEX_DEFAULT, global);
+ /* This already registers a pool cleanup */
+#endif
- return APR_SUCCESS;
}
/* Top level pool scope, need process-scope lifetime */
@@ -91,13 +113,7 @@ apr_status_t apu_dso_init(apr_pool_t *pool)
parent = apr_pool_parent_get(pool))
pool = parent;
- dsos = apr_hash_make(pool);
-
-#if APR_HAS_THREADS
- ret = apr_thread_mutex_create(&mutex, APR_THREAD_MUTEX_DEFAULT, pool);
- /* This already registers a pool cleanup */
-#endif
-
+ /* ... to be decremented on cleanup */
apr_pool_cleanup_register(pool, NULL, apu_dso_term,
apr_pool_cleanup_null);