关于FD_CLOEXEC的一个故事 http://leave001.blog.163.com/blog/static/162691293201251810343121/
2015-09-16 14:49
549 查看
关于FD_CLOEXEC的一个故事
2012-06-18 10:34:03| 分类: linux | 标签:fd_cloexec |举报|字号 订阅下载LOFTER客户端
周末翻开《UNIX环境高级编程》,读到有关FD_CLOEXEC的章节时,想到以前碰到一个案例。我只记得跟FD_CLOEXEC有关系,但忘了问题的症状和细节。年代久远啊,都过去3、4年了,当时熟悉的代码和构架都忘了。
今天再仔细回忆了一下,终于想出了一些细节。我决定把它记下了,免得以后忘了。
当时那个系统有一个logic进程,用来管理各子模块的的进程。在这些子模块中,有一个语音模块voice。logic通过fork和exec来运行子进程voice。我们碰到了一个问题:语音模块运行一阵子(经过一系列的摘机、通话、挂机)后,logic会挂住。
在cm_logic中加打印跟踪,发现在对一个fd的read处阻塞住了。仔细查看这一部分代码,没有发现任何问题,有问题的只可能是voice进程。但我们当时这样认为,voice即便有问题,也不应该影响到父进程cm_logic啊。
这个问题经过了很长时间都没有解决,直到我们在voice中解决了另一个bug。建立每次通话时,voice会创建一路socket连接收rtp,然后用这个fd来索引一个连接控制块。通话结束时,需要关闭这个fd。我们发现这些fd该关闭的没有关闭,一直增加,很快就超过了一个预设的控制块数组范围,导致资源用尽,建立通话失败。这个问题比较好查,最终发现是close时传入的fd有问题。我们使用fd来索引控制块,应该传入的是该索引。但该控制块中恰巧有一个fd变量,一个兄弟误将这个作为close参数了。
在解决这个问题后,cm_logic挂死也消失了。后来分析的原因是这样:cm_logic在fork和exec执行voice时,没有指定event fd的FD_CLOEXEC属性,从而该fd在子进程voice中仍然有效。voice中关闭那个错误fd时,由于这是一个野值,在某次通话后碰巧关闭了event fd,这样就操作了event fd对应的v-node节点。v-node是系统共用,不是进程独有的,因此导致父进程cm_logic对它的读写出现异常。
这里附上APUE中对fd、open file table和v-node的讲解:
总结起来,在解决voice中那个问题前,其实可以在运行voice前通过设置event fd的FD_CLOEXEC属性(fcntl(fd, SET_FD, FD_CLOEXEC))来解决这个问题。但根源是在voice中,因此后来就没动logic代码。之前一直认为子进程不会影响父进程的想法是错误的。
相关文章推荐
- OkHttp使用教程
- Xcode7 网络请求报错:The resource could not be loaded because the App Transport Security policy requir
- Network C++表示网络结构
- Android基础入门教程——7.6.1 Socket学习网络基础准备
- http请求头及响应头等
- 组策略映射网络驱动器
- Android利用HTTP请求加载网络图片
- Https(SSL/TLS)原理详解
- http与https的区别
- Android 用httpUtils绑定setion和cookin
- Java发送HttpRequest
- HTTP协议详解
- HTTP协议详解
- python抓取网络内容
- iOS开发网络篇—数据缓存
- 网络游戏中使用促销码
- AFNetworking从指定网址下载文件的两种方式总结 - 家柱
- HTTP 协议详解
- android 第二更(后台判断网络状态,反馈到页面)
- HTTPS原理详解