socket fd泄露导致进程无法读写文件、进行网络请求问题排查

现象:一个后台进程在跑了1000多分钟后,不再写日志,同时进程还有每分钟发送的一个网络请求,在服务端也没看到日志。

排查方式:首先怀疑是进程hang住了,但是通过gdb attach到进程,再打断点到网络请求函数,发现仍然是正常的每分钟进入一次,但是会报server connect failed错误。说明进程仍在正常执行,只是写日志和网络请求都是失败了。

因此怀疑是进程的fd满了。用ps命令查看进程id,然后执行ll /proc/12260/fd打印进程的fd信息,发现socket数量达到了1006多个,再加上一些管道,刚好是1024个。

再用ulimit -a查看系统的进程最大fd数open files的值,正好为1024,说明是因为进程的fd满了,导致写日志和发送网络请求都失败了。

接下来就是排查出现fd泄露的位置。通过lsof -p 12260查看进程占用socket fd的类型,发现是UDP类型。在程序中,创建UDP套接字的只有一个位置,是通过socket+ioctl获取本机ip的函数,确认了该函数确实没有close掉fd,并且该函数也是一分钟调用一次。

结论:系统设置了进程最大的fd数量,创建socket会消耗fd,并且当fd到达最大值时无法再创建。使用linux原生的socket函数时需要记得close fd,否则会出现fd泄露问题。

posted on 2020-03-25 20:12  proxytang  阅读(1122)  评论(0编辑  收藏  举报

导航