Add reference counting around the thread state hash table.
authorRichard Levitte <levitte@openssl.org>
Sat, 27 Sep 2003 20:29:11 +0000 (20:29 +0000)
committerRichard Levitte <levitte@openssl.org>
Sat, 27 Sep 2003 20:29:11 +0000 (20:29 +0000)
Unfortunately, this means that the dynamic ENGINE version just went up, and
isn't backward compatible.
PR: 678

crypto/engine/engine.h
crypto/err/err.c
crypto/err/err.h

index 84fb5a2a62d166fc3c43e8b1c892eef56f64c12b..9c3ab182d3799aab2945d6a07a3ae7cfd01ce8d0 100644 (file)
@@ -538,10 +538,10 @@ void ENGINE_add_conf_module(void);
 /**************************/
 
 /* Binary/behaviour compatibility levels */
-#define OSSL_DYNAMIC_VERSION           (unsigned long)0x00010100
+#define OSSL_DYNAMIC_VERSION           (unsigned long)0x00010200
 /* Binary versions older than this are too old for us (whether we're a loader or
  * a loadee) */
-#define OSSL_DYNAMIC_OLDEST            (unsigned long)0x00010100
+#define OSSL_DYNAMIC_OLDEST            (unsigned long)0x00010200
 
 /* When compiling an ENGINE entirely as an external shared library, loadable by
  * the "dynamic" ENGINE, these types are needed. The 'dynamic_fns' structure
index b873270c049ad7cd0373001390f2b326f20607e9..633a1addfe8cf1c8bb8465a5bd195838565d4abb 100644 (file)
@@ -225,6 +225,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 *);
@@ -239,6 +240,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 *);
@@ -252,6 +254,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,
@@ -271,6 +274,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
@@ -417,11 +421,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;
@@ -436,6 +466,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;
        }
 
@@ -453,6 +484,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;
        }
 
@@ -469,13 +501,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);
        }
@@ -845,6 +879,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;
index 988ef81aa0dcf7aabe1faa9f36692637e9929c69..8faa3a7b4f5560ada5b64bed057efe69fdce4bc6 100644 (file)
@@ -278,6 +278,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);