From 73029dca5aacef7083a41e61c9e0842c012c452c Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Fri, 4 Nov 2011 13:08:37 +0100 Subject: [PATCH] ssluse.c: fix calling of OpenSSL's ERR_remove_state(0) Move calling of ERR_remove_state(0) a.k.a ERR_remove_thread_state(NULL) from Curl_ossl_close_all() to Curl_ossl_cleanup(). In this way ERR_remove_state(0) is now only called in libcurl by curl_global_cleanup(). Previously it would get called by functions curl_easy_cleanup(), curl_multi_cleanup and potentially each time a connection was removed from a connection cache leading to premature destruction of OpenSSL's thread local state hash. Multi-threaded apps using OpenSSL enabled libcurl should still call function ERR_remove_state(0) or ERR_remove_thread_state(NULL) at the very end end of threads that do not call curl_global_cleanup(). --- lib/ssluse.c | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/lib/ssluse.c b/lib/ssluse.c index d65fd98..af70fe0 100644 --- a/lib/ssluse.c +++ b/lib/ssluse.c @@ -123,6 +123,10 @@ #define X509_STORE_set_flags(x,y) Curl_nop_stmt #endif +#if OPENSSL_VERSION_NUMBER >= 0x10000000L +#define HAVE_ERR_REMOVE_THREAD_STATE 1 +#endif + /* * Number of bytes to read from the random number seed file. This must be * a finite value (because some entropy "files" like /dev/urandom have @@ -697,21 +701,28 @@ int Curl_ossl_init(void) /* Global cleanup */ void Curl_ossl_cleanup(void) { - /* Free the SSL error strings */ - ERR_free_strings(); - - /* EVP_cleanup() removes all ciphers and digests from the table. */ + /* Free ciphers and digests lists */ EVP_cleanup(); #ifdef HAVE_ENGINE_CLEANUP + /* Free engine list */ ENGINE_cleanup(); #endif #ifdef HAVE_CRYPTO_CLEANUP_ALL_EX_DATA - /* this function was not present in 0.9.6b, but was added sometimes - later */ + /* Free OpenSSL ex_data table */ CRYPTO_cleanup_all_ex_data(); #endif + + /* Free OpenSSL error strings */ + ERR_free_strings(); + + /* Free thread local error state, destroying hash upon zero refcount */ +#ifdef HAVE_ERR_REMOVE_THREAD_STATE + ERR_remove_thread_state(NULL); +#else + ERR_remove_state(0); +#endif } /* @@ -960,17 +971,6 @@ void Curl_ossl_session_free(void *ptr) */ int Curl_ossl_close_all(struct SessionHandle *data) { - /* - ERR_remove_state() frees the error queue associated with - thread pid. If pid == 0, the current thread will have its - error queue removed. - - Since error queue data structures are allocated - automatically for new threads, they must be freed when - threads are terminated in oder to avoid memory leaks. - */ - ERR_remove_state(0); - #ifdef HAVE_OPENSSL_ENGINE_H if(data->state.engine) { ENGINE_finish(data->state.engine); -- 2.7.4