summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard Levitte <levitte@openssl.org>2003-09-27 20:29:05 +0000
committerRichard Levitte <levitte@openssl.org>2003-09-27 20:29:05 +0000
commit11171f3c743f6b56f4bca523053cebf5c15ecccc (patch)
tree6538603a18ca440dc1b51ca93c934c78bfa13740
parentba9f80c5d515c9e087b942f578954925290f4fb9 (diff)
Add reference counting around the thread state hash table.
Unfortunately, this means that the dynamic ENGINE version just went up, and isn't backward compatible. PR: 678
-rw-r--r--crypto/err/err.c42
-rw-r--r--crypto/err/err.h1
2 files changed, 42 insertions, 1 deletions
diff --git a/crypto/err/err.c b/crypto/err/err.c
index 9b9bec6850..f2c322c1cb 100644
--- a/crypto/err/err.c
+++ b/crypto/err/err.c
@@ -226,6 +226,7 @@ struct st_ERR_FNS
ERR_STRING_DATA *(*cb_err_del_item)(ERR_STRING_DATA *);
/* Works on the "thread_hash" error-state table */
LHASH *(*cb_thread_get)(int create);
+ void (*cb_thread_release)(LHASH **hash);
ERR_STATE *(*cb_thread_get_item)(const ERR_STATE *);
ERR_STATE *(*cb_thread_set_item)(ERR_STATE *);
void (*cb_thread_del_item)(const ERR_STATE *);
@@ -240,6 +241,7 @@ static ERR_STRING_DATA *int_err_get_item(const ERR_STRING_DATA *);
static ERR_STRING_DATA *int_err_set_item(ERR_STRING_DATA *);
static ERR_STRING_DATA *int_err_del_item(ERR_STRING_DATA *);
static LHASH *int_thread_get(int create);
+static void int_thread_release(LHASH **hash);
static ERR_STATE *int_thread_get_item(const ERR_STATE *);
static ERR_STATE *int_thread_set_item(ERR_STATE *);
static void int_thread_del_item(const ERR_STATE *);
@@ -253,6 +255,7 @@ static const ERR_FNS err_defaults =
int_err_set_item,
int_err_del_item,
int_thread_get,
+ int_thread_release,
int_thread_get_item,
int_thread_set_item,
int_thread_del_item,
@@ -272,6 +275,7 @@ static const ERR_FNS *err_fns = NULL;
* and state in the loading application. */
static LHASH *int_error_hash = NULL;
static LHASH *int_thread_hash = NULL;
+static int int_thread_hash_references = 0;
static int int_err_library_number= ERR_LIB_USER;
/* Internal function that checks whether "err_fns" is set and if not, sets it to
@@ -418,11 +422,37 @@ static LHASH *int_thread_get(int create)
CRYPTO_pop_info();
}
if (int_thread_hash)
+ {
+ int_thread_hash_references++;
ret = int_thread_hash;
+ }
CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
return ret;
}
+static void int_thread_release(LHASH **hash)
+ {
+ int i;
+
+ if (hash == NULL || *hash == NULL)
+ return;
+
+ i = CRYPTO_add(&int_thread_hash_references, -1, CRYPTO_LOCK_ERR);
+
+#ifdef REF_PRINT
+ fprintf(stderr,"%4d:%s\n",int_thread_hash_references,"ERR");
+#endif
+ if (i > 0) return;
+#ifdef REF_CHECK
+ if (i < 0)
+ {
+ fprintf(stderr,"int_thread_release, bad reference count\n");
+ abort(); /* ok */
+ }
+#endif
+ *hash = NULL;
+ }
+
static ERR_STATE *int_thread_get_item(const ERR_STATE *d)
{
ERR_STATE *p;
@@ -437,6 +467,7 @@ static ERR_STATE *int_thread_get_item(const ERR_STATE *d)
p = (ERR_STATE *)lh_retrieve(hash, d);
CRYPTO_r_unlock(CRYPTO_LOCK_ERR);
+ ERRFN(thread_release)(&hash);
return p;
}
@@ -454,6 +485,7 @@ static ERR_STATE *int_thread_set_item(ERR_STATE *d)
p = (ERR_STATE *)lh_insert(hash, d);
CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
+ ERRFN(thread_release)(&hash);
return p;
}
@@ -470,13 +502,15 @@ static void int_thread_del_item(const ERR_STATE *d)
CRYPTO_w_lock(CRYPTO_LOCK_ERR);
p = (ERR_STATE *)lh_delete(hash, d);
/* make sure we don't leak memory */
- if (int_thread_hash && (lh_num_items(int_thread_hash) == 0))
+ if (int_thread_hash_references == 1
+ && int_thread_hash && (lh_num_items(int_thread_hash) == 0))
{
lh_free(int_thread_hash);
int_thread_hash = NULL;
}
CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
+ ERRFN(thread_release)(&hash);
if (p)
ERR_STATE_free(p);
}
@@ -855,6 +889,12 @@ LHASH *ERR_get_err_state_table(void)
return ERRFN(thread_get)(0);
}
+void ERR_release_err_state_table(LHASH **hash)
+ {
+ err_fns_check();
+ ERRFN(thread_release)(hash);
+ }
+
const char *ERR_lib_error_string(unsigned long e)
{
ERR_STRING_DATA d,*p;
diff --git a/crypto/err/err.h b/crypto/err/err.h
index 1228acfe5c..d893f60bb7 100644
--- a/crypto/err/err.h
+++ b/crypto/err/err.h
@@ -293,6 +293,7 @@ ERR_STATE *ERR_get_state(void);
#ifndef OPENSSL_NO_LHASH
LHASH *ERR_get_string_table(void);
LHASH *ERR_get_err_state_table(void);
+void ERR_release_err_state_table(LHASH **hash);
#endif
int ERR_get_next_error_library(void);