C 库中的文件句柄泄漏(可能)会给 NFS 带来麻烦(+python,但这是偶然的)

Posted

技术标签:

【中文标题】C 库中的文件句柄泄漏(可能)会给 NFS 带来麻烦(+python,但这是偶然的)【英文标题】:File handle leaking (maybe) in a C library makes trouble with NFS (+python, but that's incidental) 【发布时间】:2011-05-18 16:36:15 【问题描述】:

这是一个很酷的问题。

我有一个调用 python 模块 (foo.py) 的 python 脚本 (main),该模块又调用另一个 python 模块 (barwrapper.py) 使用 LoadLibrary 动态打开和访问 libbar.so 库。

libbar 和整个链的其余部分打开并创建文件来执行它们的任务。当我们在主 python 脚本中发出一个 rmtree 以摆脱导入模块创建的临时目录时,就会出现问题。 rmtree 在脚本结束时调用,就在退出之前。调用失败是因为该目录包含.nfs-whatever 隐藏文件,我猜这是已删除的文件。这些文件显然在代码中保持打开状态,迫使 nfs 将它们移动到这些 .nfs-whatever 文件中,直到文件描述符被释放。这种情况在其他文件系统中不会出现,因为与持有的描述符相关联的文件被有效地删除,但内核仍然可以访问,直到描述符关闭。

我们强烈怀疑 .so 库正在泄漏​​文件描述符,而这些未关闭的文件在清理时破坏了 rmtree 聚会。我考虑过在 barwrapper 中卸载 .so 文件,但显然没有办法做到这一点,而且我不确定 dynloader 是否真的会从进程空间中删除 lib 并关闭描述符,或者它是否只会将其标记为已卸载就是这样,等待被其他东西替换,但描述符泄露了。

我真的想不出其他解决该问题的方法(除了修复泄漏,这是我们不想做的事情,因为它是一个 3rd 方库)。显然,它只发生在 nfs 上。您知道我们可以尝试解决它吗?

【问题讨论】:

【参考方案1】:

好的解决方案是修复句柄泄漏,但如果您不确定是谁在泄漏,也许strace 调用会帮助您定位泄漏并将错误提交给 3rd 方库的维护者(或者如果它是一个开源库更好,请尝试提交补丁;))。

另一方面,nfs 分区上的 umount/mount 可能有助于强制关闭句柄。

【讨论】:

我无法卸载集群的主分区。在任何情况下,.nfs 文件都不是永久性的。一旦我的应用程序结束,当文件描述符被释放并且内核可以释放文件(并且,我猜,同步 nfs 状态)时,它们就会消失。【参考方案2】:

内核跟踪文件描述符,所以即使你让python卸载.so并释放内存,它也不知道关闭泄露的文件描述符。唯一想到的是在分叉后导入 .so,并且只有在分叉的子进程退出后才进行清理(并且文件句柄在内核退出时隐式关闭)。

【讨论】:

以上是关于C 库中的文件句柄泄漏(可能)会给 NFS 带来麻烦(+python,但这是偶然的)的主要内容,如果未能解决你的问题,请参考以下文章

内核对象&句柄&泄漏&检测

C++/CLI 库中的早期终结和内存泄漏

如何加固linux NFS 服务安全的方法

托管窗口服务中的令牌泄漏

远程集群上的过时 NFS 文件句柄问题

C# 中的内存泄漏