summaryrefslogtreecommitdiff
path: root/crypto/apr_crypto.c
diff options
context:
space:
mode:
authorylavic <ylavic@13f79535-47bb-0310-9956-ffa450edef68>2018-06-13 09:18:19 +0000
committerylavic <ylavic@13f79535-47bb-0310-9956-ffa450edef68>2018-06-13 09:18:19 +0000
commit0a7a68f5f13c200f6043405d01ef01c340145100 (patch)
tree7eda6dae346965d4b3b78ec2d5b909a52cddeb86 /crypto/apr_crypto.c
parent29afd1aaf7bdd61972120e752c710a3409b3099b (diff)
downloadlibapr-0a7a68f5f13c200f6043405d01ef01c340145100.tar.gz
apr_crypto: follow up to r1833359: crypto libs initialization scope.
The crypto libs initialized on (and terminated with) the given pool, not the root pool. The latter is used only to maintain the active libs. This allows the users to control the scope of the lib, e.g. when itself is called by dynamic linking or DSO. git-svn-id: http://svn.apache.org/repos/asf/apr/apr/trunk@1833449 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'crypto/apr_crypto.c')
-rw-r--r--crypto/apr_crypto.c153
1 files changed, 115 insertions, 38 deletions
diff --git a/crypto/apr_crypto.c b/crypto/apr_crypto.c
index 221792d26..8b1b0888b 100644
--- a/crypto/apr_crypto.c
+++ b/crypto/apr_crypto.c
@@ -33,7 +33,6 @@
#include "apr_crypto.h"
#include "apr_version.h"
-static apr_hash_t *crypto_libs = NULL;
static apr_hash_t *drivers = NULL;
#define ERROR_SIZE 1024
@@ -305,24 +304,56 @@ APR_DECLARE(apr_status_t) apr_crypto_get_driver(
return rv;
}
-static apr_status_t crypto_libs_cleanup(void *arg)
+struct crypto_lib {
+ const char *name;
+ apr_pool_t *pool;
+ apr_status_t (*term)(void);
+ struct crypto_lib *next;
+};
+static apr_hash_t *active_libs = NULL;
+static struct crypto_lib *spare_libs = NULL;
+
+static apr_status_t crypto_libs_cleanup(void *nil)
{
- apr_hash_index_t *hi;
+ active_libs = NULL;
+ spare_libs = NULL;
+ return APR_SUCCESS;
+}
- for (hi = apr_hash_first(NULL, crypto_libs); hi; hi = apr_hash_next(hi)) {
- const char *name = apr_hash_this_key(hi);
- if (name) {
- apr_crypto_lib_term(name);
- }
+static void spare_lib_push(struct crypto_lib *lib)
+{
+ lib->name = NULL;
+ lib->pool = NULL;
+ lib->term = NULL;
+ lib->next = spare_libs;
+ spare_libs = lib;
+}
+
+static struct crypto_lib *spare_lib_pop(void)
+{
+ struct crypto_lib *lib;
+ lib = spare_libs;
+ if (lib) {
+ spare_libs = lib->next;
+ lib->next = NULL;
}
- crypto_libs = NULL;
+ return lib;
+}
+
+static apr_status_t crypto_lib_cleanup(void *arg)
+{
+ struct crypto_lib *lib = arg;
+
+ apr_hash_set(active_libs, lib->name, APR_HASH_KEY_STRING, NULL);
+ lib->term();
+ spare_lib_push(lib);
return APR_SUCCESS;
}
-APR_DECLARE(int) apr_crypto_lib_is_initialized(const char *name)
+APR_DECLARE(int) apr_crypto_lib_is_active(const char *name)
{
- return crypto_libs && apr_hash_get(crypto_libs, name, APR_HASH_KEY_STRING);
+ return active_libs && apr_hash_get(active_libs, name, APR_HASH_KEY_STRING);
}
APR_DECLARE(apr_status_t) apr_crypto_lib_init(const char *name,
@@ -331,123 +362,169 @@ APR_DECLARE(apr_status_t) apr_crypto_lib_init(const char *name,
apr_pool_t *pool)
{
apr_status_t rv;
- apr_pool_t *parent;
+ apr_pool_t *rootp, *p;
+ struct crypto_lib *lib;
if (!name) {
return APR_EINVAL;
}
- if (apr_crypto_lib_is_initialized(name)) {
+ if (apr_crypto_lib_is_active(name)) {
return APR_EREINIT;
}
- while ((parent = apr_pool_parent_get(pool))) {
- pool = parent;
+ rootp = pool;
+ while ((p = apr_pool_parent_get(rootp))) {
+ rootp = p;
}
- if (!crypto_libs) {
- crypto_libs = apr_hash_make(pool);
- if (!crypto_libs) {
+ if (!active_libs) {
+ active_libs = apr_hash_make(rootp);
+ if (!active_libs) {
return APR_ENOMEM;
}
- apr_pool_cleanup_register(pool, NULL, crypto_libs_cleanup,
+ apr_pool_cleanup_register(rootp, NULL, crypto_libs_cleanup,
apr_pool_cleanup_null);
}
+ lib = spare_lib_pop();
+ if (!lib) {
+ lib = apr_pcalloc(rootp, sizeof(*lib));
+ if (!lib) {
+ return APR_ENOMEM;
+ }
+ }
+ lib->pool = pool;
+
rv = APR_ENOTIMPL;
#if APU_HAVE_OPENSSL
if (!strcmp(name, "openssl")) {
rv = apr__crypto_openssl_init(params, result, pool);
+ if (rv == APR_SUCCESS) {
+ lib->term = apr__crypto_openssl_term;
+ lib->name = "openssl";
+ }
}
else
#endif
#if APU_HAVE_NSS
if (!strcmp(name, "nss")) {
rv = apr__crypto_nss_init(params, result, pool);
+ if (rv == APR_SUCCESS) {
+ lib->term = apr__crypto_nss_term;
+ lib->name = "nss";
+ }
}
else
#endif
#if APU_HAVE_COMMONCRYPTO
if (!strcmp(name, "commoncrypto")) {
rv = apr__crypto_commoncrypto_init(params, result, pool);
+ if (rv == APR_SUCCESS) {
+ lib->term = apr__crypto_commoncrypto_term;
+ lib->name = "commoncrypto";
+ }
}
else
#endif
#if APU_HAVE_MSCAPI
if (!strcmp(name, "mscapi")) {
rv = apr__crypto_mscapi_init(params, result, pool);
+ if (rv == APR_SUCCESS) {
+ lib->term = apr__crypto_mscapi_term;
+ lib->name = "mscapi";
+ }
}
else
#endif
#if APU_HAVE_MSCNG
if (!strcmp(name, "mscng")) {
rv = apr__crypto_mscng_init(params, result, pool);
+ if (rv == APR_SUCCESS) {
+ lib->term = apr__crypto_mscng_term;
+ lib->name = "mscng";
+ }
}
else
#endif
;
if (rv == APR_SUCCESS) {
- name = apr_pstrdup(pool, name);
- apr_hash_set(crypto_libs, name, APR_HASH_KEY_STRING, name);
+ apr_hash_set(active_libs, lib->name, APR_HASH_KEY_STRING, lib);
+ apr_pool_cleanup_register(pool, lib, crypto_lib_cleanup,
+ apr_pool_cleanup_null);
+ }
+ else {
+ spare_lib_push(lib);
}
return rv;
}
-APR_DECLARE(apr_status_t) apr_crypto_lib_term(const char *name)
+static apr_status_t crypto_lib_term(const char *name)
{
apr_status_t rv;
+ struct crypto_lib *lib;
- if (!crypto_libs) {
- return APR_EINIT;
- }
-
- if (!name) {
- apr_pool_t *pool = apr_hash_pool_get(crypto_libs);
- return apr_pool_cleanup_run(pool, NULL, crypto_libs_cleanup);
- }
-
- if (!apr_hash_get(crypto_libs, name, APR_HASH_KEY_STRING)) {
+ lib = apr_hash_get(active_libs, name, APR_HASH_KEY_STRING);
+ if (!lib) {
return APR_EINIT;
}
rv = APR_ENOTIMPL;
#if APU_HAVE_OPENSSL
if (!strcmp(name, "openssl")) {
- rv = apr__crypto_openssl_term();
+ rv = APR_SUCCESS;
}
else
#endif
#if APU_HAVE_NSS
if (!strcmp(name, "nss")) {
- rv = apr__crypto_nss_term();
+ rv = APR_SUCCESS;
}
else
#endif
#if APU_HAVE_COMMONCRYPTO
if (!strcmp(name, "commoncrypto")) {
- rv = apr__crypto_commoncrypto_term();
+ rv = APR_SUCCESS;
}
else
#endif
#if APU_HAVE_MSCAPI
if (!strcmp(name, "mscapi")) {
- rv = apr__crypto_mscapi_term();
+ rv = APR_SUCCESS;
}
else
#endif
#if APU_HAVE_MSCNG
if (!strcmp(name, "mscng")) {
- rv = apr__crypto_mscng_term();
+ rv = APR_SUCCESS;
}
else
#endif
;
if (rv == APR_SUCCESS) {
- apr_hash_set(crypto_libs, name, APR_HASH_KEY_STRING, NULL);
+ rv = apr_pool_cleanup_run(lib->pool, lib, crypto_lib_cleanup);
}
return rv;
}
+APR_DECLARE(apr_status_t) apr_crypto_lib_term(const char *name)
+{
+ if (!active_libs) {
+ return APR_EINIT;
+ }
+
+ if (!name) {
+ apr_hash_index_t *hi = apr_hash_first(NULL, active_libs);
+ for (; hi; hi = apr_hash_next(hi)) {
+ name = apr_hash_this_key(hi);
+ crypto_lib_term(name);
+ }
+ return APR_SUCCESS;
+ }
+
+ return crypto_lib_term(name);
+}
+
/**
* @brief Return the name of the driver.
*