libcurl多线程超时设置不安全

摘要:
此函数设置libcurl所需的环境。通常,如果没有显式调用它,那么第一次调用curl_easy_When init()时,curl_easy_init将调用curl_global_init,在单线程环境中,这不是问题。在多线程中使用报警超时几乎是不可能的。具体来说,它类似于curl_easy_setopt的超时设置导致使用报警。如前所述,这在多线程中是不可行的。这样,在多线程中使用超时是安全的。

from http://blog.csdn.net/sctq8888/article/details/10031219

(1), 超时(timeout)

libcurl 是 一个很不错的库,支持http,ftp等很多的协议。使用库最大的心得就是,不仔细看文档,仅仅看着例子就写程序,是一件危险的事情。我的程序崩溃了,我 怀疑是自己代码写的问题,后来发现是库没用对。不仔细看文档(有时候文档本身也比较差劲,这时除了看仔细外,还要多动脑子,考虑它是怎么实现的),后果很 严重。不加思索的使用别人的库或者代码,有时候很惬意,但是出问题时,却是寝食难安的。 

1. CURLcode curl_global_init(long flags); 在多线程应用中,需要在主线程中调用这个函数。这个函数设置libcurl所需的环境。通常情况,如果不显式的调用它,第一次调用 curl_easy_init()时,curl_easy_init 会调用 curl_global_init,在单线程环境下,这不是问题。但是多线程下就不行了,因为curl_global_init不是线程安全的。在多个线 程中调用curl_easy_int,然后如果两个线程同时发现curl_global_init还没有被调用,同时调用 curl_global_init,悲剧就发生了。这种情况发生的概率很小,但可能性是存在的。

2. libcurl 有个很好的特性,它甚至可以控制域名解析的超时。但是在默认情况下,它是使用alarm + siglongjmp 实现的。用alarm在多线程下做超时,本身就几乎不可能。如果只是使用alarm,并不会导致程序崩溃,但是,再加上siglongjmp,就要命了 (程序崩溃的很可怕,core中几乎看不出有用信息),因为其需要一个sigjmp_buf型的全局变量,多线程修改它。(通常情况下,可以每个线程一个 sigjmp_buf 型的变量,这种情况下,多线程中使用 siglongjmp 是没有问题的,但是libcurl只有一个全局变量,所有的线程都会用)。

具体是类似 curl_easy_setopt(curl, CURLOPT_TIMEOUT, 30L) 的超时设置,导致alarm的使用(估计发生在域名解析阶段),如前所述,这在多线程中是不行的。解决方式是禁用掉alarm这种超时, curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1L)。

这样,多线程中使用超时就安全了。但是域名解析就没了超时机制,碰到很慢的域名解析,也很麻烦。文档的建议是 Consider building libcurl with c-ares support to enable asynchronous DNS lookups, which enables nice timeouts for name resolves without signals. c-ares 是异步的 DNS 解决方案。

引自:http://gcoder.blogbus.com/logs/54871550.html

调用libcurl下载,然后使用netstat查看发现有大量的TCP连接保持在CLOSE_WAIT状态
查看libcurl的文档说明,有这样一个选项:

CURLOPT_FORBID_REUSE

Pass a long. Set to 1 to make the next transfer explicitly close the connection when done. Normally, libcurl keeps all connections alive when done with one transfer in case a succeeding one follows that can re-use them. This option should be used with caution and only if you understand what it does. Set to 0 to have libcurl keep the connection open for possible later re-use (default behavior). 

也就是说,默认情况下libcurl完成一个任务以后,出于重用连接的考虑不会马上关闭
如果没有新的TCP请求来重用这个连接,那么只能等到CLOSE_WAIT超时,这个时间默认在7200秒甚至更高,太多的CLOSE_WAIT连接会导致性能问题

解决方法:


curl_easy_setopt(curl, CURLOPT_FORBID_REUSE, 1); 

最好再修改一下TCP参数调低CLOSE_WAIT和TIME_WAIT的超时时间

免责声明:文章转载自《libcurl多线程超时设置不安全》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇docker API接口service update错误记录 error while removing network:…pyqt5学习之QCheckbox下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

JMeter学习(一)工具简单介绍

一、JMeter介绍 Apache JMeter是100%纯JAVA桌面应用程序,被设计为用于测试客户端/服务端结构的软件(例如web应用程序)。它可以用来测试静态和动态资源的性能,例如:静态文件,Java Servlet,CGI Scripts,Java Object,数据库和FTP服务器等等。JMeter可用于模拟大量负载来测试一台服务器,网络或者对象...

IP address could not be resolved: Name or service not known

[root@test ~]# /usr/local/mysql/bin/mysqld2018-08-05T07:00:33.647509Z 0 [Warning] [MY-011070] [Server] 'Disabling symbolic links using --skip-symbolic-links (or equivalent) is the...

mysql主从之多线程复制

多线程复制 mysql 主从复制原理: 1. master 节点上的binlogdump 线程,在slave 与其正常连接的情况下,将binlog 发送到slave 上。 2. slave 节点的I/O Thread ,通过读取master 节点binlog 日志名称以及偏移量信息将其拷贝到本地relay log 日志文件。 3. slave 节点的SQL...

Jmeter性能测试-jp@gc

本文参考了:https://www.cnblogs.com/yagao/p/12614175.html   Throughput Shaping Timer 是用来控制吞吐量的定时器,通过延缓线程运行来整体控制取样器产生的RPS。 实际使用中: 1. 可以通过设置在不同吞吐量分别持续一段时间,考察系统在不同吞吐量情况下的稳定性 2. 可以通过设置随着时间持...

AndroidSchedulers.mainThread()无法切换到主线程,原来是细节问题啊

Observable.create(new Observable.OnSubscribe<Integer>() { @Override public void call(Subscriber<? super Integer> subscriber) {...

抓取网页数据(金融股市实时数据)

最近查了几天的资料去写一个网页抓取股票实时数据的程序,网上一堆资料都是翻来覆去的讲解同样的方法,还有都是抓取一般的没有变化的对时间要求不要的网页数据,然而对于股票实时数据的抓取要求的是每秒钟都会由很多股票数据在发生变化,要保证程序能抓取到每秒钟这些变化着的数据,好了,出于这个目的开始在网上搜说数据,很多人建议用libcurl方法,好的,libcurl很强大...