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 *);
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 *);
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,
* 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
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;
p = (ERR_STATE *)lh_retrieve(hash, d);
CRYPTO_r_unlock(CRYPTO_LOCK_ERR);
+ ERRFN(thread_release)(&hash);
return p;
}
p = (ERR_STATE *)lh_insert(hash, d);
CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
+ ERRFN(thread_release)(&hash);
return p;
}
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);
}
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;