Andrew, 1. I'm using 0.9.6 so I don't know if what I write here applies to your OpenSSL version. Initializing SSL_CTX once before spawning threads should work. I have SSL_CTX be initialized in a static class so I'm sure SSL_CTX is ready first and goes away when the process is shutdown (any lingering threads will fail of course in this case). (I'm passing SSLv23_client_method() to SSL_CTX_new call).
2. Also, if you are running on Solaris you will see that the default hash id created for thread slots is not a very good one: it uses the pid which will probably be the same for all threads :) In your version of OpenSSl check if in cryptlib.c the CRYPTO_thread_id function returns getpid() when in SOLARIS. You will notice that id_callback will be NULL if you don't set an id_callback via CRYPTO_set_id_callback. If this is the case, then this is probably your problem. Make sure that you provide a "sane" implementation to generate IDs by calling CRYPT_set_id_callback function when you are initializing the SSL context (you need to this only once per process obviously). You can use pthreads_thread_id(void ); or solaris_thread_id(void ); (in crypto/threads/th-locks.c ) functions as the callback functions to generate the hash for thread slot ids. For example: // Set function to create hash for slot ID CRYPTO_set_id_callback(solaris_thread_id); I hope this helps Emilio -----Original Message----- From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED] Behalf Of Andrew Mann Sent: Monday, September 08, 2003 9:35 AM To: [EMAIL PROTECTED]; [EMAIL PROTECTED] Subject: SSL_CTX_new race condition I appologize if this comes through twice. I haven't seen the first come through the list yet and it was sent Friday, so I presume it's been gobbled up somewhere :) I'm working on an application that needs to work with a lot of simultaneous SSL connections to the same remote host. It spawns a thread for each connection and handles each connection entirely in that thread. These connections each last anywhere from half a second to a minute, and as soon as the connection is finished, it's closed and the thread is terminated (and often another thread started to process another request). The OpenSSL library is initialized prior to any connection handling thread starting. Apparently thread safety is a FAQ, but the answer on the www.openssl.org FAQ and related links falls far short of helpful and borders on just plain inaccurate. Initially I tried using a single SSL_CTX for all connections, so that while no SSL objects were being shared across threads, one SSL_CTX object was being used to all calls to SSL_new(). This failed miserably. SSL connections failed randomly and frequently during the negotation phase. The SSL_CTX ended up getting freed on some test runs during the middle of the run. Although there are suggestions that a single SSL_CTX is meant to be shared between multiple connections, there isn't any specific mention of wether that is supposed to work with connections handled by different threads, so I suppose it's not (well it appears not to at least). I moved to making a new SSL_CTX for each thread as well. This had somewhat better luck, but randomly during startup one of the calls to SSL_CTX_new() would fail with "error:140A90A1:SSL routines:SSL_CTX_new:library has no ciphers". After a bit of digging it appears that SSL_CTX_new() is not really threadsafe either. It calls ssl_create_cipher_list() which checks the status of an unmutexed global variable init_ciphers (ssl/ssl_ciph.c). If the value is its initialization value of 1, then load_ciphers() is called. load_ciphers() sets init_ciphers to 0 and then procedes to load various ciphers for the library to use. Unfortunately, since this value isn't protected by a mutex it's not unlikely that in the event of two threads "racing" through SSL_CTX_new() that the lead thread will clear init_ciphers and then be interrupted before it can actually perform any loading. For the time being I've worked around this by creating a SSL_CTX prior to starting any threads that has no point other than to prompt cipher loading before any potential race conditions. Fixes: I'm not sure about the SSL_CTX shared between threads, but it would be nice if the settings (CA files particularly) didn't have to be loaded from disk for each thread spawned in this scenario. Protect init_ciphers with a mutex. Or at least move init_ciphers=0 to the end of the load_ciphers() function so that the worst case condition becomes multiple calls to load_ciphers() instead of a tiny chance of multiple calls and a larger chance of a"library has no ciphers" error. Andrew ______________________________________________________________________ OpenSSL Project http://www.openssl.org User Support Mailing List [EMAIL PROTECTED] Automated List Manager [EMAIL PROTECTED] ______________________________________________________________________ OpenSSL Project http://www.openssl.org User Support Mailing List [EMAIL PROTECTED] Automated List Manager [EMAIL PROTECTED]