Commit 11171f3c authored by Richard Levitte's avatar Richard Levitte
Browse files

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
parent ba9f80c5
Loading
Loading
Loading
Loading
+41 −1
Original line number Diff line number Diff line
@@ -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;
+1 −0
Original line number Diff line number Diff line
@@ -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);