Hi,
I am running libvirt with ESXi driver in multithread scenario to access ESXi by https.
Sometimes a core dump will be generated as following:
#0 0x0000003f9b030265 in raise () from /lib64/libc.so.6
#1 0x0000003f9b031d10 in abort () from /lib64/libc.so.6
#2 0x0000003f9b06a84b in __libc_message () from /lib64/libc.so.6
#3 0x0000003f9b072fae in _int_malloc () from /lib64/libc.so.6
#4 0x0000003f9b074cde in malloc () from /lib64/libc.so.6
#5 0x0000003f9b07963b in strerror () from /lib64/libc.so.6
#6 0x0000003fa188032a in ERR_load_ERR_strings () from /lib64/libcrypto.so.6
#7 0x0000003fa187fde9 in ERR_load_crypto_strings () from /lib64/libcrypto.so.6
#8 0x0000003fa48309d9 in SSL_load_error_strings () from /lib64/libssl.so.6
#9 0x00002aaaba8e612e in Curl_ossl_init () from
/opt/CSCOppm-unit/hypervisor/libcurl/lib/libcurl.so.4
#10 0x00002aaaba8ee6c1 in curl_global_init () from
/opt/CSCOppm-unit/hypervisor/libcurl/lib/libcurl.so.4
#11 0x00002aaaba8ee6f8 in curl_easy_init () from
/opt/CSCOppm-unit/hypervisor/libcurl/lib/libcurl.so.4
#12 0x00002aaaba0d932b in esxVI_SessionIsActive (ctx=0x2aaac093ca80,
sessionID=0x2aaac06932a0 "`3i\300\252*", userName=0x2aaac0ae6e80
"root", output=0xffffffffffffffff) at esx/esx_vi_methods.generated.c:599
#13 0x00002aaaba0c7a60 in esxStorageVolumeLookupByKey (conn=0x7412, key=0x76c1 <Address
0x76c1 out of bounds>) at esx/esx_storage_driver.c:825
I checked that currently ESXi driver didn't initialize openssl. Because libcurl will
not handle openssl for multi-thread. According to openssl API, libvirt should
register two methods to support mutli-threads. The detailed description is as following:
http://www.openssl.org/docs/crypto/threads.html
I have changed code as following:
1. virInitialize() in libvirt.c
Old Code:
int
virInitialize(void)
{
...
virLogSetFromEnv();
virNetTLSInit();
...
}
New Code:
int
virInitialize(void)
{
...
virLogSetFromEnv();
virNetTLSInit();
virOpenSSLInit();
...
}
2. In virnetServer.c
New Code:
pthread_mutex_t *lock_cs;
long *lock_count;
void virOpenSSLLockCallback(int mode, int type, const char *file ATTRIBUTE_UNUSED, int
line ATTRIBUTE_UNUSED) {
if (mode & CRYPTO_LOCK)
{
pthread_mutex_lock(&(lock_cs[type]));
lock_count[type]++;
}
else
{
pthread_mutex_unlock(&(lock_cs[type]));
}
}
unsigned long virOpenSSLIdCallback(void)
{
unsigned long ret;
ret=(unsigned long)pthread_self();
return(ret);
}
void virOpenSSLInit(void)
{
int i;
lock_cs=OPENSSL_malloc(CRYPTO_num_locks() * sizeof(pthread_mutex_t));
lock_count=OPENSSL_malloc(CRYPTO_num_locks() * sizeof(long));
for (i=0; i<CRYPTO_num_locks(); i++)
{
lock_count[i]=0;
pthread_mutex_init(&(lock_cs[i]),NULL);
}
CRYPTO_set_id_callback(virOpenSSLIdCallback);
CRYPTO_set_locking_callback(virOpenSSLLockCallback);
}
To be honest, virOpenSSLInit/ virOpenSSLIdCallback/ virOpenSSLLockCallback should not be
defined in this file. But It seems that Makefile generated by autoconfig can't
handle the new file recursively.
What about this solution? If you have any comments, please feel free to contact me.
BTW: If I add a new source/header file, is there a simple way to change Makefile?
B.R.
Benjamin Wang