Libcurl多线程crash问题_delphiwcdj的博客-CSDN博客_curl_global_init崩溃


本站和网页 https://blog.csdn.net/delphiwcdj/article/details/18284429 的作者无关,不对其内容负责。快照谨为网络故障时之索引,不代表被搜索网站的即时页面。

Libcurl多线程crash问题_delphiwcdj的博客-CSDN博客_curl_global_init崩溃
Libcurl多线程crash问题
delphiwcdj
于 2014-01-15 00:26:51 发布
24120
收藏
分类专栏:
Apache
HTTP
C/C++
TCP/IP
GNU/Linux
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/delphiwcdj/article/details/18284429
版权
Apache
同时被 3 个专栏收录
7 篇文章
0 订阅
订阅专栏
HTTP
16 篇文章
0 订阅
订阅专栏
C/C++
194 篇文章
1 订阅
订阅专栏
 2014-01-15 wcdj
1 问题背景
后台系统有一个单线程的http接口,为了提高并发处理能力,开启多个线程并发在跑,修改后接口的响应确实得到提高,但是server每3分钟出现一次crash。原因是系统使用的是curl-7.21.1(August 11 2010)的库,此版本并非线程安全。遂替换了最新的curl-7.34.0(December 12 2013)库,悲催的是时隔几小时还是会偶现crash,于是再仔细阅读官方文档。
官方对最新版本libcurl的Multi-threading Issues解释如下[1]:
The first basic rule is that you mustneversimultaneously share a libcurl handle (be it easy or multi or whatever) betweenmultiple threads. Only use one handle in one thread at any time. You can passthe handles around among threads, but you must never use a single handle frommore than one thread at any given time.
libcurl is completely thread safe, except for two issues:signals and SSL/TLS handlers. Signals are used for timingout name resolves (during DNS lookup) - when built without c-ares support andnot on Windows.
When using multiple threads youshould set the CURLOPT_NOSIGNAL option to 1 for all handles.Everything will or might work fine except that timeouts are not honored duringthe DNS lookup - which you can work around by building libcurl with c-aressupport. c-ares is a library that provides asynchronous name resolves.On some platforms, libcurl simply will not function properlymulti-threaded unless this option is set.
Also, note that CURLOPT_DNS_USE_GLOBAL_CACHE is notthread-safe.
此接口并没有使用到SSL/TLS,但会不会是用到了signals导致的crash呢?官方建议在多线程场景下应该设置CURLOPT_NOSIGNAL选项,因为在解析DNS出现超时的时候将会发生“糟糕”的情况。官方也给出了解决方法,可以使用c-ares[2]的libcurl版本实现异步域名解析来预防这种“糟糕”的情况,但是最后一句还是告诫我们:在多线程场景下,若不设置CURLOPT_NOSIGNAL选项,可能会有“意外”的情况发生。通过官方这段描述,可以大致猜测到是没有设置这个选项造成的crash。下面是官方对此选项的说明[3]:
CURLOPT_NOSIGNAL
Pass a long. If it is 1, libcurl will not use anyfunctions that install signal handlers or any functions that cause signals tobe sent to the process.This option is mainly here toallow multi-threaded unix applications to still set/use all timeout optionsetc, without risking getting signals. The default value for thisparameter is 0. (Added in 7.10)
If this option is set and libcurl has been built withthe standard name resolver, timeouts will not occur while the name resolvetakes place. Consider building libcurl with c-ares support to enableasynchronous DNS lookups, which enables nice timeouts for name resolves withoutsignals.
Setting CURLOPT_NOSIGNALto 1 makes libcurl NOT ask the system to ignore SIGPIPE signals, whichotherwise are sent by the system when trying to send data to a socket which isclosed in the other end.libcurl makes an effort tonever cause such SIGPIPEs to trigger, but some operating systems have no way toavoid them and even on those that have there are some corner cases when theymay still happen, contrary to our desire. In addition, usingCURLAUTH_NTLM_WBauthentication could cause a SIGCHLD signal to be raised.
即CURLOPT_NOSIGNAL选项的作用是,在多线程处理场景下使用超时选项时,会忽略signals对应的处理函数,但是官方也“无奈地”解释说,这个选项只是“尽量”去避免产生signals,但是在一些操作系统或“极少数的”情况下,还是有产生signals的情况发生。意思是还是有小概率的crash情况发生,这个只能在现网的机器验证了。
仔细看下后台系统接口的实现,发现确实有用到设置超时选项的代码:
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, timeout);
curl_easy_setopt(curl, CURLOPT_TIMEOUT, timeout);
这两个选项在官方的解释分别是:
CURLOPT_CONNECTTIMEOUT
Pass a long. It should contain the maximum time inseconds that you allow the connection to the server to take. This only limitsthe connection phase, once it has connected, this option is of no more use. Setto zero to switch to the default built-in connection timeout - 300 seconds. Seealso the CURLOPT_TIMEOUToption.
In unix-like systems, thismight cause signals to be used unless CURLOPT_NOSIGNAL is set.
CURLOPT_TIMEOUT
Pass a long as parameter containing the maximum timein seconds that you allow the libcurl transfer operation to take. Normally,name lookups can take a considerable time and limiting operations to less thana few minutes risk aborting perfectly normal operations. This option will causecurl to use the SIGALRM to enable time-outing system calls.
In unix-like systems, thismight cause signals to be used unless CURLOPT_NOSIGNAL is set.
Default timeout is 0 (zero) which means it nevertimes out.
因此,虽然替换了最新thread-safe的libcurl库,但是这两行设置超时选项的代码,会导致signal发生产生线程安全性问题,因而还是会偶尔出现crash。
2 遗留问题
在官方的Multi-threading Issues描述中并没有提及curl_global_init[4-5]的线程安全问题,而在curl_global_init(3)的接口描述中,提及了curl_global_init是非线程安全的。
This function sets up the program environment thatlibcurl needs. Think of it as an extension of the library loader.
This function must be called atleast once within a program (a program is all the code that shares a memoryspace) before the program calls any other function in libcurl.The environment it sets up is constant for the life of the program and is thesame for every program, so multiple calls have the same effect as one call.
The flags option is a bit pattern that tells libcurlexactly what features to init, as described below. Set the desired bits byORing the values together.In normal operation, youmust specify CURL_GLOBAL_ALL. Don't use any other value unless you arefamiliar with it and mean to control internal operations of libcurl.
This function is not thread safe.You must not call it when any other thread in the program (i.e. a threadsharing the same memory) is running. This doesn't just mean no other threadthat is using libcurl. Because curl_global_init()calls functions of other libraries that are similarly thread unsafe, it couldconflict with any other thread that uses these other libraries.
See the description in libcurl(3)of global environment requirements for details of how to use this function.
因此,在多线程的环境下,程序一开始需要先显示地调用一次curl_global_init,这样在工作线程处理每次请求调用curl_easy_init()时,判断curl_global_init是否调用过,从而避免再次调用curl_global_init以减少冲突的概率。例如,可以这样初始化:
static bool bInit = false;
if (bInit == false)
bInit= true;
curl_global_init(CURL_GLOBAL_ALL);
CURL *curl = curl_easy_init();
if (!curl)
//error handle
3 官网一个多线程的例子
/* A multi-threaded example that uses pthreads extensively to fetch
* X remote files at once */
#include <stdio.h>
#include <pthread.h>
#include <curl/curl.h>
#define NUMT 4
/*
List of URLs to fetch.
If you intend to use a SSL-based protocol here you MUST setup the OpenSSL
callback functions as described here:
http://www.openssl.org/docs/crypto/threads.html#DESCRIPTION
*/
const char * const urls[NUMT]= {
"http://curl.haxx.se/",
"ftp://cool.haxx.se/",
"http://www.contactor.se/",
"www.haxx.se"
};
static void *pull_one_url(void *url)
CURL *curl;
curl = curl_easy_init();
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_perform(curl); /* ignores error */
curl_easy_cleanup(curl);
return NULL;
/*
int pthread_create(pthread_t *new_thread_ID,
const pthread_attr_t *attr,
void * (*start_func)(void *), void *arg);
*/
int main(int argc, char **argv)
pthread_t tid[NUMT];
int i;
int error;
/* Must initialize libcurl before any threads are started */
curl_global_init(CURL_GLOBAL_ALL);
for(i=0; i< NUMT; i++) {
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++) {
error = pthread_join(tid[i], NULL);
fprintf(stderr, "Thread %d terminated\n", i);
return 0;
更多例子:http://curl.haxx.se/libcurl/c/multithread.html
4 参考
[1] http://curl.haxx.se/libcurl/c/libcurl-tutorial.html
[2] http://curl.haxx.se/mail/lib-2010-11/0188.html
[3] http://curl.haxx.se/libcurl/c/curl_easy_setopt.html#CURLOPTNOSIGNAL
[4] http://curl.haxx.se/libcurl/c/curl_global_init.html
[5] http://code.lovemiao.com/?tag=multi-thread
delphiwcdj
关注
关注
点赞
收藏
打赏
评论
Libcurl多线程crash问题
2014-01-15 wcdj1 问题背景后台系统有一个单线程的http接口,为了提高并发处理能力,开启多个线程并发在跑,修改后接口的响应确实得到提高,但是server每3分钟出现一次crash。原因是系统使用的是curl-7.21.1(August 11 2010)的库,此版本并非线程安全。遂替换了最新的curl-7.34.0(December 12 2013)库,悲催的
复制链接
扫一扫
专栏目录
libcurl长连接高并发高性能封装测试分析源代码
09-19
项目中需要用到Curl频繁调用的情况,发现curl接口调用速度缓慢。为了实现curl高性能,高并发,需要研究如何实现高性能高并发。研究方向有三个。
(1)长连接。考虑采用长连接的方式去开发。首先研究下长连接和短连接的性能区别。curl内部是通过socket去连接通讯。socket每次连接最为耗时,如果能够复用连接,长时间连接,减少每次socket连接的时间,则可以大大减少时间,提高效率。
(2)多线程。单个线程下载速度毕竟有限,使用多线程去调用接口。实现高并发高性能,需要考虑资源分配和冲突的问题。
(3)异步调用。和socket异步调用的原理类似。同步调用会阻塞等待,造成CPU占用率高。
评论 2
您还未登录,请先
登录
后发表或查看评论
美团一面:为什么线程崩溃崩溃不会导致 JVM 崩溃
最新发布
m0_71777195的博客
12-05
153
网上看到一个很有意思的美团面试题:为什么线程崩溃崩溃不会导致 JVM 崩溃,这个问题我看了不少回答,但发现都没答到根上,所以决定答一答,相信大家看完肯定会有收获,本文分以下几节来探讨线程崩溃,进程一定会崩溃吗进程是如何崩溃的-信号机制简介为什么在 JVM 中线程崩溃不会导致 JVM 进程崩溃openJDK 源码解析一般来说如果线程是因为非法访问内存引起的崩溃,那么进程肯定会崩溃,为什么系统要让进程崩溃呢,这主要是因为在进程中,各个线程的地址空间是共享的,既然是共享,那么某个线程对地址的非法访问就会导致内存的
libcurl的curl_easy_perform奔溃问题
typ2004的专栏
09-09
9505
curl_global_init(CURL_GLOBAL_ALL);
curl_global_cleanup();
这两个是libcurl全局函数,负责环境的初始化和清理。
非线程安全,对于多线程来说,请不要再每个线程里都初始化和清理。一个简单的做法是在主线程里初始化和清理。
This function sets up the program environment tha
curl_multi异步高并发服务
因热爱而执着,因执着而成功。
10-08
115
curl_multi_poll和curl_multi_wait区别有两个,一个是curl_multi_poll在被等待的时间内,可以调用curl_multi_wakeup激活,curl_multi_poll会加速返回。没有找到解决办法,可能和多线程调用有关。(4) 一次向multihand添加1000条任务,curl_multi_perform执行返回任务从1000降到0后,并不是所有分任务都执行完了,读取的数据也就600条左右,需要多次调用curl_multi_info_read去读取数据。
解决使用 libcurl 遇到的多线程崩溃问题
Roc Cliff
12-04
3847
使用 curl 访问 http 链接时,用 easy handle,阻塞方式访问时发现会每个访问启动一个线程去进行dns
想减少这种消耗,故此采用了 sh = curl_share_init(); curl_share_setopt(sh, CURLSHOPT_SHARE, CURL_LOCK_DATA_DNS);来启用dns
cache功能,工作的挺好
后面在多个线程里使用同一个 sh
浅析libcurl多线程安全问题
fei的专栏
07-09
1万+
浅析libcurl多线程安全问题
背景:使用多线程libcurl发送请求,在未设置超时或长超时的情况下程序运行良好。但只要设置了较短超时(小于180s),程序就会出现随机的coredump。并且栈里面找不到任何有用的信息。
问题:1.为什么未设置超时,或者长超时时间(比如601s)的情况下多线程libcurl不会core?
问题:2.进程coredump并不是必现,是否在libc
libcurl多线程下载器新版
07-23
基于libcurl/pthreads的多线程下载器,跨平台,支持暂停、还原、中止,断点续传,支持HTTP,HTTPS协议链接,http://blog.csdn.net/u012532305/article/details/46709495也是这篇文章的源码,此版本修复上一版本发现的问题
curl_easy_init 多线程使用导致的崩溃
wishes2018的博客
01-30
6331
当多个线程,同时进行curl_easy_init时,由于会调用非线程安全的curl_global_init,因此导致崩溃。
应该在主线程优先调用curl_global_init进行全局初始化。再在线程中使用curl_easy_init。
示例代码
/***************************************************************************...
libcurl Multi异步接口使用
洛的博客
03-21
2551
1、multi异步接口实现文件上传demo
《1》、设置easy接口
#include <curl/curl.h>
#include <curl/multi.h>
/* mutil 句柄的最大连接数 */
#define MAX_CONNECT_HANDLE_NUMS (15)
/* 客制化的私有数据结构体 */
typedef struct CustomPrivD...
多线程调用libcurl基于https会导致的crash
无与伦比BLOG
04-26
1240
今天发现如果使用多线程调用curl_easy的接口,并发访问若干https的接口,程序会出现偶尔的崩溃。崩溃位于调用curl_easy_cleanup的时候,最后崩溃的函数位于LIBEAY32.dll中的getrn。google搜索之后发现这是libcurl在使用openssl的时候,根据openssl版本的不同,可能需要设置回调的函数https://curl.haxx.se/libcurl/c/...
libcurl入门之相关接口函数curl_global_init/cleanup
霍宏鹏的专栏
03-06
1331
名称:curl_global_init
原型
#include <curl/curl.h>
CURLcode curl_global_init(longflags);
描述
这个函数设置libcurl需要的程序运行环境,可以把它看作一个的加载器扩展
在进程环境(所有代码共享内存地址空间的程序)下,libcurl其他所有函数被调用之前这函数至少需要被调用一次。在进程的生命周期内,这个环境设置是没有变化的,所以在同一个程序中,多次调用和只调用一次没有区别。
这个flags选项精确.
libcurl多线程下载
07-14
基于libcurl/pthreads的多线程下载器,跨平台,支持暂停、还原、中止,断点续传,支持HTTP,HTTPS协议链接,http://blog.csdn.net/u012532305/article/details/46709495也是这篇文章的源码
libcurl 多线程使用注意事项(补充)——HTTPS,openssl多线程使用加锁
热门推荐
jaylong35的专栏
11-18
1万+
问题
多线程libcurl运行一段时间后出现崩掉,没有确定的点,没有确定的URL。一直查看源代码没有问题,最后通过debug跟踪发现是在访问SSL的时候出现的crash。
才想起来openssl是不支持多线程的,要自己做加锁处理。而且libcurl中并没有支持相关的加锁操作。
解决办法:
在初始化libcurl的时候为openssl创建一个互斥锁函数,一个回调函数传给openss
libcurl 多线程使用注意事项
Balder~专栏
05-24
1万+
(1), 超时(timeout)
libcurl 是 一个很不错的库,支持http,ftp等很多的协议。使用库最大的心得就是,不仔细看文档,仅仅看着例子就写程序,是一件危险的事情。我的程序崩溃了,我 怀疑是自己代码写的问题,后来发现是库没用对。不仔细看文档(有时候文档本身也比较差劲,这时除了看仔细外,还要多动脑子,考虑它是怎么实现的),后果很 严重。不加思索的使用别人的库或者代码,有时候很惬意,
libcurl崩溃
sbfksmq的博客
10-26
1224
在编译完libcurl的dll和lib后,使用如下
// http.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <stdio.h>
#include <curl/curl.h>
#pragma comment(lib,"libcurl.lib")
int _tmain(int argc, _TCHAR* a...
C语言libcurl例程:multi 多线程,多任务
RToax
04-23
2465
目录
A multi-threaded example that uses pthreads to fetch several files at once
multi_socket API using libuv
using the multi interface to do a single download
using the multi interface to do a multi...
初识 libcurl multi:实现一个 http 请求处理客户端,一个线程玩命发一个线程吐血收
(ÒωÓױ)
02-18
759
一、引言
最近在工作中,遇到了这么一个需求:
我们希望拥有一个高性能的 http 请求处理客户端程序,这个客户端要求有这样的架构:
它拥有两个线程
一个线程接收业务程序通过消息队列发来的批量的 http 请求信息,进行批量的 http 请求
另一个线程接收外部的 http 应答,并将应答信息放到本地的消息队列中供业务程序使用
要求在 http 请求的处理过程中,尽量保持不阻塞高性能处理
这...
curl使用小记(四)——在多线程中使用的问题总结
人生海海 山山而川
11-07
885
在多线程中使用CURL的问题总结
“相关推荐”对你有帮助么?
非常没帮助
没帮助
一般
有帮助
非常有帮助
提交
©️2022 CSDN
皮肤主题:大白
设计师:CSDN官方博客
返回首页
delphiwcdj
CSDN认证博客专家
CSDN认证企业博客
码龄16年
暂无认证
442
原创
3万+
周排名
111万+
总排名
231万+
访问
等级
2万+
积分
788
粉丝
165
获赞
248
评论
350
收藏
私信
关注
热门文章
Mac上Homebrew的使用 (Homebrew 使 OS X 更完整)
130427
Linux下获取线程TID的方法——gettid()
61369
将一个十六进制字符串转换为十进制数值的问题
59528
使用Docker registry镜像创建私有仓库
57629
VS2008中Run-Time Check Failure #2 - Stack around the variable 'xxx' was corrupted 错误解决方法
47275
分类专栏
Go in Action
14篇
Algorithm
38篇
Apache
7篇
Applied Cryptography
10篇
Assembly
1篇
Awk
4篇
Bash
7篇
Boost
6篇
C/C++
194篇
C11/C++11
7篇
C++沉思录
8篇
Coroutine
2篇
Debug
5篇
Docker
16篇
English
12篇
GCC
5篇
GNU/Linux
114篇
GoLang
28篇
Genericity
1篇
Git/GitHub
5篇
Life
9篇
Lua
2篇
LaTeX
1篇
Math
Mac OS X/iOS
45篇
MySQL
18篇
OpenGL
8篇
Perl
14篇
Python
15篇
PHP
4篇
Plotting/Datavis
3篇
Regex
8篇
Serialization/Protobuf
2篇
Serialization/MessagePack
1篇
TCP/IP
22篇
Tcl/OTcl
22篇
Tools
11篇
Vi/Vim
10篇
Sublime Text
1篇
VC/MFC
24篇
VPS/SAE
1篇
VPS/DigitalOcean
WSN
1篇
HTTP
16篇
Nginx
6篇
XML
1篇
HTML
10篇
CSS
8篇
分布式
2篇
服务器硬件
架构设计
代码优化
Redis
1篇
最新评论
Libcurl使用OpenSSL编译出现undefined reference to `COMP_CTX_free'错误备忘
qq_31556517:
不能解决
GoLang之”奇怪用法“实践总结
ReganYue:
少年,我看你骨骼精奇,不如来我博客看看可好
Linux IPC之内存映射mmap()
junLinlong:
好详细,感谢博主
VS2008中Run-Time Check Failure #2 - Stack around the variable 'xxx' was corrupted 错误解决方法
FengLu_:
感谢!终于知道自己的代码出了什么问题了
Linux IPC之内存映射mmap()
qq_40862235:
非常详细
您愿意向朋友推荐“博客详情页”吗?
强烈不推荐
不推荐
一般般
推荐
强烈推荐
提交
最新文章
Effective C++ - Inheritance and Object-Oriented Design
Effective C++ - Implementations
Redis简单入门
2017年10篇
2016年33篇
2015年37篇
2014年43篇
2013年36篇
2012年37篇
2011年100篇
2010年127篇
2009年45篇
目录
目录
分类专栏
Go in Action
14篇
Algorithm
38篇
Apache
7篇
Applied Cryptography
10篇
Assembly
1篇
Awk
4篇
Bash
7篇
Boost
6篇
C/C++
194篇
C11/C++11
7篇
C++沉思录
8篇
Coroutine
2篇
Debug
5篇
Docker
16篇
English
12篇
GCC
5篇
GNU/Linux
114篇
GoLang
28篇
Genericity
1篇
Git/GitHub
5篇
Life
9篇
Lua
2篇
LaTeX
1篇
Math
Mac OS X/iOS
45篇
MySQL
18篇
OpenGL
8篇
Perl
14篇
Python
15篇
PHP
4篇
Plotting/Datavis
3篇
Regex
8篇
Serialization/Protobuf
2篇
Serialization/MessagePack
1篇
TCP/IP
22篇
Tcl/OTcl
22篇
Tools
11篇
Vi/Vim
10篇
Sublime Text
1篇
VC/MFC
24篇
VPS/SAE
1篇
VPS/DigitalOcean
WSN
1篇
HTTP
16篇
Nginx
6篇
XML
1篇
HTML
10篇
CSS
8篇
分布式
2篇
服务器硬件
架构设计
代码优化
Redis
1篇
目录
评论 2
被折叠的 条评论
为什么被折叠?
到【灌水乐园】发言
查看更多评论
打赏作者
delphiwcdj
你的鼓励将是我创作的最大动力
¥2
¥4
¥6
¥10
¥20
输入1-500的整数
余额支付
(余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付
您的余额不足,请更换扫码支付或充值
打赏作者
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额
抵扣说明:
1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。 2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。
余额充值