summaryrefslogtreecommitdiff
path: root/util-misc
diff options
context:
space:
mode:
authorGraham Leggett <minfrin@apache.org>2019-06-23 23:13:03 +0000
committerGraham Leggett <minfrin@apache.org>2019-06-23 23:13:03 +0000
commita8ef9b25706d3ce1c5c2cb1b6adcf872d9e9d2c9 (patch)
tree65596fc49bb78ebef721f07d19bdc64fab242ff6 /util-misc
parent24ef67941e1b63f6e633f2688976ce35b77dbd51 (diff)
downloadapr-a8ef9b25706d3ce1c5c2cb1b6adcf872d9e9d2c9.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: https://svn.apache.org/repos/asf/apr/apr/trunk@1861957 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'util-misc')
-rw-r--r--util-misc/apu_dso.c48
1 files changed, 32 insertions, 16 deletions
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);