Hi guys,
I'm trying to find the source of a deadlock issue concerning apache
(2.2.22 with APR-1.4.6) and openssl-1.0.0j. From what I can see I have
the exact same situation as in
https://issues.apache.org/bugzilla/show_bug.cgi?id=53870 but the patch
referenced there (http://cvs.openssl.org/chngview?cn=22570) only fixed a
part of the deadlock cases. I was able to confirm it did help using gdb
but as I said it only helped to fix some of the deadlocks.
There are still hundreds of threads trying to aquire a
CRYPTO_LOCK_EVP_PKEY lock and getting stuck on it because someone is
never releasing it. I searched the openssl source for places where such
a type of lock is used and stumbled onto this here
openssl-1.0.1c/crypto/asn1/x_pubkey.c (+175)
/* Check to see if another thread set key->pkey first */
CRYPTO_w_lock(CRYPTO_LOCK_EVP_PKEY);
if (key->pkey)
{
EVP_PKEY_free(ret);
ret = key->pkey;
}
else
key->pkey = ret;
CRYPTO_w_unlock(CRYPTO_LOCK_EVP_PKEY);
CRYPTO_add(&ret->references, 1, CRYPTO_LOCK_EVP_PKEY);
Isn't this a bit risky ? What if this code is interrupted just before
executing the last line of the snippet above and then some other thread
does
CRYPTO_w_lock(CRYPTO_LOCK_EVP_PKEY);
EVP_PKEY_free(key->pkey);
CRYPTO_w_unlock(CRYPTO_LOCK_EVP_PKEY);
I suggest doing
/* Check to see if another thread set key->pkey first */
int alrdy_set = 0;
CRYPTO_add(&ret->references, 1, CRYPTO_LOCK_EVP_PKEY);
CRYPTO_w_lock(CRYPTO_LOCK_EVP_PKEY);
if (key->pkey)
{
EVP_PKEY_free(ret);
ret = key->pkey;
alrdy_set=1;
}
else
key->pkey = ret;
CRYPTO_w_unlock(CRYPTO_LOCK_EVP_PKEY);
if (!alrdy_set)
CRYPTO_add(&ret->references, -1, CRYPTO_LOCK_EVP_PKEY);
Regards,
Thomas
______________________________________________________________________
OpenSSL Project http://www.openssl.org
Development Mailing List openssl-dev@openssl.org
Automated List Manager majord...@openssl.org