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);
}
* will be returned for SYSerr(), which always gets an errno
* value and never one of those 'standard' reason codes. */
-static void build_SYS_str_reasons()
+static void build_SYS_str_reasons(void)
{
/* OPENSSL_malloc cannot be used here, use static storage instead */
static char strerror_tab[NUM_SYS_STR_REASONS][LEN_SYS_STR_REASON];
#define err_clear(p,i) \
do { \
- es->err_flags[i]=0; \
- es->err_buffer[i]=0; \
+ (p)->err_flags[i]=0; \
+ (p)->err_buffer[i]=0; \
err_clear_data(p,i); \
- es->err_file[i]=NULL; \
- es->err_line[i]= -1; \
+ (p)->err_file[i]=NULL; \
+ (p)->err_line[i]= -1; \
} while(0)
static void ERR_STATE_free(ERR_STATE *s)
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;
{
unsigned long ret,l;
- l=((ERR_STRING_DATA *)a_void)->error;
+ l=((const ERR_STRING_DATA *)a_void)->error;
ret=l^ERR_GET_LIB(l)^ERR_GET_FUNC(l);
return(ret^ret%19*13);
}
/* static int err_cmp(ERR_STRING_DATA *a, ERR_STRING_DATA *b) */
static int err_cmp(const void *a_void, const void *b_void)
{
- return((int)(((ERR_STRING_DATA *)a_void)->error -
- ((ERR_STRING_DATA *)b_void)->error));
+ return((int)(((const ERR_STRING_DATA *)a_void)->error -
+ ((const ERR_STRING_DATA *)b_void)->error));
}
/* static unsigned long pid_hash(ERR_STATE *a) */
static unsigned long pid_hash(const void *a_void)
{
- return(((ERR_STATE *)a_void)->pid*13);
+ return(((const ERR_STATE *)a_void)->pid*13);
}
/* static int pid_cmp(ERR_STATE *a, ERR_STATE *b) */
static int pid_cmp(const void *a_void, const void *b_void)
{
- return((int)((long)((ERR_STATE *)a_void)->pid -
- (long)((ERR_STATE *)b_void)->pid));
+ return((int)((long)((const ERR_STATE *)a_void)->pid -
+ (long)((const ERR_STATE *)b_void)->pid));
}
void ERR_remove_state(unsigned long pid)
else
str=p;
}
- strcat(str,a);
+ BUF_strlcat(str,a,(size_t)s+1);
}
}
ERR_set_error_data(str,ERR_TXT_MALLOCED|ERR_TXT_STRING);
int ERR_set_mark(void)
{
- int i=0;
ERR_STATE *es;
es=ERR_get_state();
int ERR_pop_to_mark(void)
{
- int i=0;
ERR_STATE *es;
es=ERR_get_state();