程序跑的好好的,改成多线程就各种segfault 了,看到都心累,只能gdb 慢慢调了,每次都是在ssl_connect的时候就出错,认真重新检查了一遍ssl_connect 之前的所有步骤,man 了个个函数,发现SSL_library_init() 是不可重入的,openssl的官网也有说明,1.1.0 之前的版本SSL connect是不支持并行的,要是升级openssl 库估计更大工程,原来的很多模块都是根据openssl 1.0.1 实现的,升级是不现实的,只能先修改程序,使得它在openssl1.0.1 下多线程能跑得好好的,折腾一番下来,总算改好了。总结一下,要在1.0.1的openssl库下编写多线程的代码的解决方法:
1.确认openssl 库编译的时候打开了支持多线程的开关,在openssl库的源码目录下面的install 文件有说明,默认是用threads 参数的, 就是支持多线程的,有些系统还需要-D_REENTRANT 参数,./configure 的时候记得带上这些参数;
2.用到SSL_library_init 等不可重入的函数的时候,要加锁;
3.在crypto 库里面还有设置两个回调函数,使用例子可参考openssl源码目录下面的crypto/threads/mttest.c,主要就是在线程开始之
前设置两个回调函数,这两个回调函数分别是获取线程id和加锁的函数,贴一下关键代码,如下:
-
static pthread_mutex_t *lock_cs;
-
static long *lock_count;
-
-
线程开始之前先注册回调函数,就是为每一个线程注册一个lock,当调用crypto库里面的函数的时候,可通过
-
回调函数加锁
-
-
void thread_setup(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((unsigned long (*)())pthreads_thread_id);
-
CRYPTO_set_locking_callback((void (*)())pthreads_locking_callback);
-
}
-
-
线程结束之后,释放空间
-
void thread_cleanup(void)
-
{
-
int i;
-
-
CRYPTO_set_locking_callback(NULL);
-
fprintf(stderr,"cleanup\n");
-
for (i=0; i<CRYPTO_num_locks(); i++)
-
{
-
pthread_mutex_destroy(&(lock_cs[i]));
-
fprintf(stderr,"%8ld:%s\n",lock_count[i],
-
CRYPTO_get_lock_name(i));
-
}
-
OPENSSL_free(lock_cs);
-
OPENSSL_free(lock_count);
-
-
fprintf(stderr,"done cleanup\n");
-
}
-
-
回调函数一,加锁用的函数
-
void pthreads_locking_callback(int mode, int type, char *file,
-
int line)
-
{
-
-
if (mode & CRYPTO_LOCK)
-
{
-
pthread_mutex_lock(&(lock_cs[type]));
-
lock_count[type]++;
-
}
-
else
-
{
-
pthread_mutex_unlock(&(lock_cs[type]));
-
}
-
}
-
-
回调函数二,返回线程id ,用来取得对应的锁
-
unsigned long pthreads_thread_id(void)
-
{
-
unsigned long ret;
-
-
ret=(unsigned long)pthread_self();
-
return(ret);
-
}
总结一下,发现man 和官网绝对是个好东西,没事可以多读读man 手册,尤其各个API 的用法,存在的缺陷都会有说明。
阅读(4012) | 评论(0) | 转发(0) |