diff options
author | minfrin <minfrin@13f79535-47bb-0310-9956-ffa450edef68> | 2019-06-23 23:13:03 +0000 |
---|---|---|
committer | minfrin <minfrin@13f79535-47bb-0310-9956-ffa450edef68> | 2019-06-23 23:13:03 +0000 |
commit | c946743e4c77b787f98d9f6b677c2e34dfdbcb39 (patch) | |
tree | 65596fc49bb78ebef721f07d19bdc64fab242ff6 | |
parent | b04f0aa2a44e31b5cf9dcca714a2f43e71f2b1ad (diff) | |
download | libapr-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-- | CHANGES | 5 | ||||
-rw-r--r-- | util-misc/apu_dso.c | 48 |
2 files changed, 37 insertions, 16 deletions
@@ -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); |