今天发现如果使用多线程调用curl_easy的接口,并发访问若干https的接口,程序会出现偶尔的崩溃。崩溃位于调用curl_easy_cleanup的时候,最后崩溃的函数位于LIBEAY32.dll中的getrn。google搜索之后发现这是libcurl在使用openssl的时候,根据openssl版本的不同,可能需要设置回调的函数
https://curl.haxx.se/libcurl/c/threadsafe.html
我的libcurl是使用vcpkg安装的,它依赖的openssl版本为1.0.2o,因此需要设置回调函数locking_function和threadid_func。当然,openssl 1.0.2的文档也提到
threadid_func(CRYPTO_THREADID *id) is needed to record the currently-executing thread's identifier into id. The implementation of this callback should not fill in id directly, but should use CRYPTO_THREADID_set_numeric() if thread IDs are numeric, or CRYPTO_THREADID_set_pointer() if they are pointer-based. If the application does not register such a callback using CRYPTO_THREADID_set_callback(), then a default implementation is used - on Windows and BeOS this uses the system's default thread identifying APIs, and on all other platforms it uses the address of errno. The latter is satisfactory for thread-safety if and only if the platform has a thread-local error number facility.
也就是说windows上有获取线程ID的实现,不需要注册threadid的回调
网上的很多例子都是基于官网例子改的,使用了pthread库的相关函数
https://curl.haxx.se/libcurl/c/opensslthreadlock.html
在windows上面使用pthread并不是那么方便。可以参考基于c++11的实现
https://stackoverflow.com/questions/34998440/curl-crashes-in-threaded-calls
基于boost的实现
https://curl.haxx.se/mail/lib-2016-11/0175.html
std::vector<std::mutex> openssl_lock_list(CRYPTO_num_locks());
void openssl_crypto_locking_callback(
int mode, int type, const char * const, int)
if (mode & CRYPTO_LOCK) {
openssl_lock_list[type].lock();
else {
openssl_lock_list[type].unlock();
// 要多线程调用前先设置openssl的lock回调
CRYPTO_set_locking_callback(openssl_crypto_locking_callback);
原文链接:
https://www.jianshu.com/p/18b5ac128bb2
用
libcurl
一段时间遇到莫名其妙的程序崩溃的情况,开
会
觉得是
线程
栈溢出
导致
的段错误,专门增加了
线程
栈的大小貌似无效。
线程
也是分离的。用valgrind定位到问题可能出现在
curl
的
调用
上。
排查的时候也发现了
libcurl
一些额外的坑,现做个总结笔记。
线程
使用
libcurl
访问时,设置了超时时间,而
libcurl
库
不
会
为这个超时信号做任何处理,信号产生而没有信号句柄处理,可能导
注意点1:现象:http短连接超过一定次数后一直返回错误7,即
CURL
E_COULDNT_CONNECT
过程有打印:Immediate connect fail for 114.116.228.34: Too many open files
使用netstat查看发现有大量的TCP连接保持在CLOSE_WAIT状态:
原因:也就是说,默认情况下
libcurl
完成一个任务以后,出于重用连接的考虑不
会
马上关闭
如果没有新的TCP请求来重用这个连接,那么只能等到CLOSE_WAIT
cento :http://blog.csdn.net/delphiwcdj/article/details/18284429
1 问题背景
后台系统有一个单
线程
的http接口,为了提高并发处理能力,开启多个
线程
并发在跑,修改后接口的响应确实得到提高,但是server每3分钟出现一次
crash
。原因是系统使用的是
curl
-7.21.1(August 11 2010)的
库
,此版本并非
线程
安全。遂替换...
后台系统有一个单
线程
的http接口,为了提高并发处理能力,开启多个
线程
并发在跑,修改后接口的响应确实得到提高,但是server每3分钟出现一次
crash
。原因是系统使用的是
curl
-7.21.1(August 11 2010)的
库
,此版本并非
线程
安全。遂替换了最新的
curl
-7.34.0(December 12 2013
使用
curl
访问 http 链接时,用 easy handle,阻塞方式访问时发现
会
每个访问启动一个
线程
去进行dns
想减少这种消耗,故此采用了 sh =
curl
_share_init();
curl
_share_setopt(sh,
CURL
SHOPT_SHARE,
CURL
_LOCK_DATA_DNS);来启用dns
cache功能,工作的挺好
后面在多个
线程
里使用同一个 sh