摘要:libcurl在多线程中,采用https访问,经常运行一段时间,会出现crash。

libcurl的在多线程中的使用特别注意的有两点:

1. curl的句柄不能多线程共享。

2. ssl访问时, openssl是线程不安全的。

知道了这两点,就能解决libcurl无故crash的问题了。

第一点:每个线程初始化一个句柄,供这个线程使用。

第二点:需要添加回调函数,进行线程锁。

参考代码如下:

#include <stdio.h>
#include <pthread.h>
#include <curl/curl.h> #define NUMT 4 /* we have this global to let the callback get easy access to it */
static pthread_mutex_t *lockarray; #ifdef USE_OPENSSL
#include <openssl/crypto.h>
static void lock_callback(int mode, int type, char *file, int line)
{
(void)file;
(void)line;
if(mode & CRYPTO_LOCK) {
pthread_mutex_lock(&(lockarray[type]));
}
else {
pthread_mutex_unlock(&(lockarray[type]));
}
} static unsigned long thread_id(void)
{
unsigned long ret; ret = (unsigned long)pthread_self();
return ret;
} static void init_locks(void)
{
int i;
printf("crypto num is %d\r\n", CRYPTO_num_locks());
lockarray = (pthread_mutex_t *)OPENSSL_malloc(CRYPTO_num_locks() *
sizeof(pthread_mutex_t));
for(i = 0; i<CRYPTO_num_locks(); i++) {
pthread_mutex_init(&(lockarray[i]), NULL);
} CRYPTO_set_id_callback((unsigned long (*)())thread_id);
CRYPTO_set_locking_callback((void (*)())lock_callback);
} static void kill_locks(void)
{
int i; CRYPTO_set_locking_callback(NULL);
for(i = 0; i<CRYPTO_num_locks(); i++)
pthread_mutex_destroy(&(lockarray[i])); OPENSSL_free(lockarray);
} /* List of URLs to fetch.*/
const char * const urls[]= {
"https://www.example.com/",
"https://www2.example.com/",
"https://www3.example.com/",
"https://www4.example.com/",
}; static void *pull_one_url(void *url)
{
CURL *curl; curl = curl_easy_init();//每个线程初始化一个句柄,绝对不能混用。
curl_easy_setopt(curl, CURLOPT_URL, url);
/* this example doesn't verify the server's certificate, which means we
might be downloading stuff from an impostor */
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
curl_easy_perform(curl); /* ignores error */
curl_easy_cleanup(curl); return NULL;
} int main(int argc, char **argv)
{
pthread_t tid[NUMT];
int i;
(void)argc; /* we don't use any arguments in this example */
(void)argv; /* Must initialize libcurl before any threads are started */
curl_global_init(CURL_GLOBAL_ALL); init_locks();//初始化openssl的回调函数,加载线程锁 for(i = 0; i< NUMT; i++) {
int error = pthread_create(&tid[i],
NULL, /* default attributes please */
pull_one_url,
(void *)urls[i]);
if(0 != error)
fprintf(stderr, "Couldn't run thread number %d, errno %d\n", i, error);
else
fprintf(stderr, "Thread %d, gets %s\n", i, urls[i]);
} /* now wait for all threads to terminate */ for(i = 0; i< NUMT; i++) {
pthread_join(tid[i], NULL);
fprintf(stderr, "Thread %d terminated\n", i);
} kill_locks();//销毁openssl线程锁 return 0;
}

最新文章

  1. Zookeeper常用命令
  2. 转载:JProfiler远程监控LINUX上的Tomcat过程细讲
  3. sublime text2小技巧
  4. Unity烂笔头1-自定义INSPECTOR属性窗口节点项
  5. 转载js实现打印功能
  6. 【git】借助github学习成果
  7. css的clip裁剪
  8. VSTO 学习笔记(十三)谈谈VSTO项目的部署
  9. Ubuntu下hadoop2.4搭建集群(单机模式)
  10. 转:loadrunner经典面试题
  11. poj1006中国剩余定理
  12. yum 安装zabbix2.4 /3.2.4
  13. Win下必备神器之Cmder
  14. python复习购物车程序
  15. 不使用DataContext直接将ViewModels绑定到ItemsControl控件
  16. css3整理--Animation
  17. OC动画:CAAnimationGroup
  18. linux 乌班图 安装pycharm
  19. Mycat的简易安装及测试
  20. 第4章 文件和目录(5)_贯穿案例2:mini shell(1)

热门文章

  1. 设置项目的日程排定方式(Project)
  2. java 多线程:线程安全问题synchronized关键字解决
  3. 7.2 Tornado异步
  4. UE4之第一个飞机游戏
  5. Lucene 基础类型
  6. 关于 TCP/IP
  7. BBN+
  8. Android物联网应用程序开发(智慧城市)—— 查询购物信息界面开发
  9. 【MySQL作业】MySQL函数——美和易思数学函数和控制流函数应用习题
  10. 编写Java程序,在子类老虎中重写父类动物的吃食方法