最近使用QT开发跨平台局域网集群系统,遇到“GLib-ERROR **: Creating pipes for GWakeup: 打开的文件过多”这个问题,并且实际测试在Windows系统下该问题出现的概率低,但是在Linux系统下,该问题每次出现,并且会导致程序崩溃。

网上搜索了一下该问题的解决办法,比较多的是这种方法:

在Ubuntu下使用QT创建的软件运行时创建多线程出现GLib-ERROR **:Creating pipes for GWakeup: Too many open files错误提示信息;此错误是因进程创建的线程个数超过Ubuntu 限制的每个进程可创建线程个数导致,在终端输入如下命令修改最大值即可:

ulimit -n 4096

 但是我的问题使用这个方法并没有解决问题。

另外有一篇文章说的很对,出现问题说明代码肯定存在问题,即便通过上述方法解决了问题,那肯定也存在隐患,原话是:

可是,这思路不对啊.明明是程序问题,扩大数量是能解决一时问题,时间一长照样嗝屁.说到底还是程序问题.可是打开了哪些文件?使用这个办法:

lsof -p 进程id > openfiles.log

接着我在stackoverflow网上得到一些启示,说在Linux下一切皆文件,这里拓展一下:

Linux一切皆文件

一切皆文件

  • 首先通常在windows中是文件的东西,它们在linux中也是文件
  • 其次一些在windows中不是文件的东西, 比如进程, 磁盘, 也被抽象成了文件. 你可以使用访问文件的方法访问它们获得信息.
  • 再其次,一些很离谱的东西, 比如管道, 比如/dev/zero(一个可以读出无限个0的文件) /dev/null(一个重定向进去之后就消失了的文件). 它们也是文件
  • 再再其次, 类似于socket这样的东西, 使用的接口跟文件接口也是一致的.

带来的好处就是, 你可以使用同一套api(read, write)和工具(cat , 重定向, 管道)来处理unix中大多数的资源.这就使得组合了简单的命令和字符处理工具(awk, sed)之后, shell脚本就能发挥出强大的功能.

----------------分割线---------------

意识到Linux下一切皆文件让我醍醐灌顶,一下子豁然开朗,知道了为什么我的问题在Linux下明显而在Windows下不明显了,所以虽然我的问题显示是“打开文件过多”,而实际上是由于我打开的网络连接过多,没及时关闭!

后来实测在Windows下重复多次扫描请求,问题依然会出现,程序会崩溃,所以说Windows平台下当时没出问题只是表象。

定位到问题的原因我就想办法解决问题,中间也尝试了各种方法,不过后来想着最直接的方法就是及时关闭不需要的socket,虽然QT下基于QObject的类在new后会在适当的时候自动释放,但是要注意这也可能存在问题,比如它没能在适当的时候释放,比如我这次就遇到了这种问题。

解决办法:手动控制socket连接请求的释放,在不必要的时候即时清理多余的socket连接。

至此问题解决,因为代码比较繁杂,这里就不给出代码了,只给出思路,希望能帮助到有需要的人。

 

Logo

更多推荐