当前位置: 首页 > news >正文

libcurl多线程超时设置不安全

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的超时时间

相关文章:

  • 可视化库-Matplotlib-直方图(第四天)
  • 微信支付JSAPI,实测!终极方案
  • 【转载】关于nginx以及内核参数的配置
  • Material Design设计规范在ComponentOne For WinForm的应用(上)
  • 从数据中心基础设施的视角来看 Facebook 机器学习的应用
  • 073:【Django数据库】ORM聚合函数详解-Count
  • 2019年如何成为全栈工程师?
  • 原生 js 实现移动端 Touch 滑动反弹
  • 文章正在审核中 为什么使用了爬虫代理ip,真实IP还是被封禁了?
  • elasticsearch-head插件安装
  • Git 常用命令
  • [转]Introduction of iSCSI Target in Windows Server 2012
  • 【转】理解红黑树
  • FastDFS-图片服务器
  • Volo.Abp.EntityFrameworkCore.MySQL 使用
  • [Vue CLI 3] 配置解析之 css.extract
  • [微信小程序] 使用ES6特性Class后出现编译异常
  • 【node学习】协程
  • Angular数据绑定机制
  • centos安装java运行环境jdk+tomcat
  • create-react-app做的留言板
  • download使用浅析
  • Fastjson的基本使用方法大全
  • JS题目及答案整理
  • js中forEach回调同异步问题
  • Laravel深入学习6 - 应用体系结构:解耦事件处理器
  • 从 Android Sample ApiDemos 中学习 android.animation API 的用法
  • 精彩代码 vue.js
  • 如何解决微信端直接跳WAP端
  • 什么是Javascript函数节流?
  • 腾讯大梁:DevOps最后一棒,有效构建海量运营的持续反馈能力
  • 通过git安装npm私有模块
  • 系统认识JavaScript正则表达式
  • 一份游戏开发学习路线
  • python最赚钱的4个方向,你最心动的是哪个?
  • ​configparser --- 配置文件解析器​
  • #pragma once与条件编译
  • $.ajax()方法详解
  • (BFS)hdoj2377-Bus Pass
  • (附源码)spring boot校园健康监测管理系统 毕业设计 151047
  • (附源码)ssm本科教学合格评估管理系统 毕业设计 180916
  • (简单) HDU 2612 Find a way,BFS。
  • (十一)手动添加用户和文件的特殊权限
  • ****** 二 ******、软设笔记【数据结构】-KMP算法、树、二叉树
  • ... 是什么 ?... 有什么用处?
  • .360、.halo勒索病毒的最新威胁:如何恢复您的数据?
  • .describe() python_Python-Win32com-Excel
  • .desktop 桌面快捷_Linux桌面环境那么多,这几款优秀的任你选
  • .NET MVC第三章、三种传值方式
  • .NET 应用启用与禁用自动生成绑定重定向 (bindingRedirect),解决不同版本 dll 的依赖问题
  • .vue文件怎么使用_我在项目中是这样配置Vue的
  • [ solr入门 ] - 利用solrJ进行检索
  • [ vulhub漏洞复现篇 ] Django SQL注入漏洞复现 CVE-2021-35042
  • [2009][note]构成理想导体超材料的有源THz欺骗表面等离子激元开关——
  • [AIGC 大数据基础]hive浅谈