“爱提踢斯”项目最近遇到一个问题,当FTP服务器磁盘没有空间时,设备会不断复位——这是测试人员反馈的。我们拿到log后,看到一个通信所用的文件打开失败。不断打印Too many open file,然后超时设备复位。同时我们看到数据库文件打开失败,无法写入数据。一个现象,看到好几处问题。还是从最初的表现来入手。虽然把bug指派给别人,但从时间、进度上考虑,周末还是去加班。而最后,解决了问题。根据老夫目测,是FTP的socket未关闭引起的。

linux系统的文件句柄(我很想说“文件描述符”,但“句柄”似乎更多人使用)是有限制的。查看系统支持句柄最大值用如下命令:
# ulimit -n
1024

可见,默认是1024。

下面用代码来说明一下问题。代码如下:

/**
系统一次允许最大的文件句柄为1024。
open foobar file for: 340
open bar file for: 340
open foo file for: 341
open foobar file failed: : Too many open files
open BAR file failed: : Too many open files# ulimit  -a
...
open files                      (-n) 1024
...
*/#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>int foo(void)
{static int cnt = 1;int ret = 0;int fd =-1;char buf[5] = {0};char read_buf[5] = {0};fd = open("/tmp/FOO.txt",O_RDWR|O_CREAT,0666);if(fd < 0){perror("open FOO file failed: ");return -1;}printf("open foo file for: %d\n", cnt++);return 0;
}int bar(void)
{static int cnt = 1;int ret = 0;int fd =-1;char buf[5] = {0};char read_buf[5] = {0};fd = open("/tmp/BAR.txt",O_RDWR|O_CREAT,0666);if(fd < 0){perror("open BAR file failed: ");return -1;}printf("open bar file for: %d\n", cnt++);return 0;
}int foobar(void)
{static int cnt = 1;int ret = 0;int fd =-1;char buf[5] = {0};char read_buf[5] = {0};fd = open("/tmp/foobar.txt",O_RDWR|O_CREAT,0666);if(fd < 0){perror("open foobar file failed: ");return -1;}printf("open foobar file for: %d\n", cnt++);return 0;
}int main(void)
{int ret = 0;while (1) {foo();usleep(1);foobar();usleep(1);ret = bar();// if (ret < 0) break; // 不让其退出usleep(100);}return 0;
}

要查看这个进程占用文件句柄数,先获取该进程PID:
# ps -ef | grep a.out     
root     17835  7615 17 23:01 pts/1    00:00:00 ./a.out

我们查看该进程文件句柄最大值:
# cat /proc/17835/limits | grep "files"
Max open files            1024                 4096                 files  
和系统默认值一样。查看已占用值:
# ll /proc/17835/fd | wc -l 
1027

我们看到,已经占用上千个句柄,一直未释放。当达到系统最大值时,就会报Too many open files的错误。

匆匆已然四载,不曾想到,当年刚入职搞FTP的我,竟然会埋下地雷,让今天的我不幸踩中。在没有离职情况下,只好义无反顾地去解决bug。——而这个bug,正是因为未关闭socket造成的。

FTP客户端的实现,是需要打开2个socket的,一个是命令通道,一个是数据通道。在服务器没有磁盘空间情况下,write数据是返回错误的,使用FTP模块者认为是无法登陆,下次会再次尝试登陆——在这种情况下,登陆是正常的,只是无法写数据。但每次登陆,都会创建命令通道的socket,这导致了socket的泄漏,不会关闭,因为使用者并没有调用logout函数退出登陆。另一个问题是最主要的,每次写数据时,要创建数据通道的socket,但在出错时,并没有关闭数据通道的socket,而是直接返回。这再次导致了socket泄漏。找到了原因,解决起来就好办了。

自从知道可以查看某个进程占用的文件句柄,我去看看以前的设备,发现有个别文件占用句柄较多——也就几十个。目测是只打开但未关闭。出于热心,我把情况在部门群里说了,至于后续的事,因为那些不是我的职责范围,不敢越趄代庖。

2015.8.1 李迟

遇到一个因socket未关闭引发的文件句柄用完问题相关推荐

  1. 加载文件流_未关闭的文件流会引起内存泄露么?

    专注于Java领域优质技术,欢迎关注 来自:技术小黑屋 最近接触了一些面试者,在面试过程中有涉及到内存泄露的问题,其中有不少人回答说,如果文件打开后,没有关闭会导致内存泄露.当被继续追问,为什么会导致 ...

  2. 一个JDK线程池BUG引发的GC机制思考

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试资料 作者:空无 来源:https://urlify.cn/63QrYv ...

  3. oracle断开不活跃链接,活跃进程连接导致数据库迟迟未关闭

    关闭数据库时,在sqlplus里面输入shutdown immediate迟迟无响应 所以查看了alertlog文件 $ cd $ORACLE_BASE $ ls admin    product $ ...

  4. Java socket中关闭IO流后,发生什么事?(以关闭输出流为例)

    为了方便讲解,我们把 DataOutputstream dout = new DataOutputStream(new BufferedOutputStream(mySocket.getOutputS ...

  5. Android编程之另一种原因造成Cursor未关闭错误

    关于异常错误:Finalizing a Cursor that has not been deactivated or closed.如果有朋友也遇到了类似的错误,又不是因为cursor没有关闭造成的 ...

  6. 记录由于未关闭加速器就关机而导致的再次启动后DNS配置错误

    记录由于未关闭加速器就关机而导致的再次启动后DNS配置错误 先直接给出解决方案: cmd输入 netsh winsock reset 这段时间在同学的推荐下入坑了鹅鹅鸭(Goose Goose Duc ...

  7. oracle open_cursors未关闭问题解决

    问题背景 DBA监控到最近生产上数据库报了ORA-01000: maximum open cursors exceeded,这个错误表示已经达到一个进程打开的最大游标数,DBA已经加了两次open_c ...

  8. 柯尼卡美能达提示关闭第一侧盖板未关闭故障

    在日常维修美能达复印机中我们经常遇见很多种机器型号的各种故障及维修错误代码,由全技术提供故障交流问题,在柯尼卡复印机的故障提示警告我们比较常见的是出现维修召唤M2代码,正常进入维修模式清除即可,柯尼卡 ...

  9. 解决出现线程未关闭 , 造成内存泄漏问题

    解决出现线程未关闭 , 造成内存泄漏问题 16-Feb-2022 16:38:24.978 警告 [main] org.apache.catalina.loader.WebappClassLoader ...

最新文章

  1. ピエタ~幸せの青い鳥~相关
  2. thinkphp-join
  3. 假笨说-类初始化死锁导致线程被打爆!打爆!爆!
  4. 零压力学python_《零压力学Python》 之 第一章知识点归纳
  5. 需求奇葩不可怕,可怕的是变幻无常
  6. docker安装elasticsearch2.4.4
  7. 【mac】iTerm2中ssh保持连接不断开
  8. postgreSQL源码分析——索引的建立与使用——GIST索引(1)
  9. mysql的底层数据结构_MySQL索引底层数据结构实现原理
  10. Android 使用JSON格式与服务器交互 中文乱码问题解决
  11. IE打开xml文件弹出下载对话框
  12. 隧道工程偷工减料大揭秘一
  13. 动易cms聚合空间最近访客访问地址错误解决方法
  14. php生成各种验证码
  15. 首届 RustCon Asia 圆满落幕——Love is electricity for RustCon Asia
  16. 从有状态应用(Session)到无状态应用(JWT),以及 SSO 和 OAuth2
  17. linux 查看nas磁盘阵列,NAS(linux)阵列管理
  18. server 08 做DNS和域分离
  19. 什么是 DOM 和 BOM?
  20. IPFS未来展望,迎接Web3.0新潮流

热门文章

  1. 苹果供应商:iPhone SE 3 5G和AirPods生产平稳
  2. 近4年个人收款码数据将被追查补税?微信、支付宝紧急回应了
  3. 抖音起诉腾讯垄断 要求停止封禁并索赔9000万元
  4. 微信 8.0.1又来了!修复问题,终于能显示“在线状态”了
  5. 京东健康暗盘涨幅超27% 成交额超1.6亿港元
  6. 苹果挥刀,iPhone 12 mini要换处理器了,无缘A14!
  7. 任正非:将来华为岗位分三类 职员类岗位不涉及末位淘汰
  8. 特斯拉加州工厂无视禁令强行复工,马斯克:要抓就只抓我
  9. 微信灰度测试“相关阅读”功能 公众号文章下推荐延伸内容
  10. 京东拼多多全面封杀电子烟,淘宝仍正常销售...