NFS 上的多处理 python 从 os.cwd() 获取“没有这样的文件或目录”

问题描述 投票:0回答:1

我一直在对 EL9 环境中的测试用例进行故障排除,该测试用例在 EL7 环境中的行为有所不同。

具体来说:

  • 在 NFS 安装上。
  • 发生在我们的 EL9 系统 (5.14.0-362.18.1.el9_3.x86_64) 上。在我们任何较旧的 Centos 7 系统(3.10 内核各种版本)上都不会出现这种情况。
  • 在子目录中。 (在“顶级”坐骑中不会发生)。
  • 代码经常“中断”,
    os.cwd()
    返回“没有这样的文件或目录”。

转载于:

  • 5.14.0-427.el9.x86_64(阿尔玛)
  • 5.14.0-362.24.1.el9_3.x86_64(阿尔玛)
  • 5.14.0-362.18.1.el9_3.x86_64(阿尔玛)
  • 5.14.0-362.8.1.el9_3.x86_64(RHEL)

复制代码示例:

#!/usr/bin/python3 -u

import os
import multiprocessing
import time

if __name__=="__main__":
    multiprocessing.set_start_method("spawn")

    count = 0
    while True:
        try:
            os.getcwd()
            pool = multiprocessing.Pool(10)
            pool.close()
            pool.terminate()
            count += 1
        except Exception as e:
            print(f"Failed after {count} iterations")
            print(e)
            break

我有点不知所措,不明白这里发生了什么,以及它为什么会失败。

它似乎与

pool.terminate()
有关,就好像您在此之前添加哪怕是短暂的(0.05)睡眠,问题就会停止发生(至少,在“合理”的时间内无法重现,而上述方法在 <10 iterations).

中失败)

有趣的是

cwd
保持不一致:

build-2[myuser]:[~/python_race]$ ./simple.py 
Failed after 2 iterations
[Errno 2] No such file or directory
build-2[myuser]:[~/python_race]$ ./simple.py 
Traceback (most recent call last):
  File "<frozen importlib._bootstrap_external>", line 1362, in _path_importer_cache
KeyError: '.'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "./simple.py", line 4, in <module>
    import multiprocessing
  File "<frozen importlib._bootstrap>", line 1007, in _find_and_load
  File "<frozen importlib._bootstrap>", line 982, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 925, in _find_spec
  File "<frozen importlib._bootstrap_external>", line 1423, in find_spec
  File "<frozen importlib._bootstrap_external>", line 1392, in _get_spec
  File "<frozen importlib._bootstrap_external>", line 1364, in _path_importer_cache
  File "<frozen importlib._bootstrap_external>", line 1340, in _path_hooks
  File "<frozen importlib._bootstrap_external>", line 1610, in path_hook_for_FileFinder
  File "<frozen importlib._bootstrap_external>", line 1486, in __init__
FileNotFoundError: [Errno 2] No such file or directory

这似乎是通过 chdir 来“恢复”的,或者等待我认为是 NFS 缓存到期间隔的时间。

我们之所以选择这个,是因为我们的一些测试在“新版本”上失败了,更简单:

import multiprocessing
multiprocessing.set_start_method("spawn")

while True:
    multiprocessing.Pool(10)

但正如前面提到的 - 特定于 NFS 挂载在子目录中,我们认为这可能是因为

struct dentry
在根挂载上的行为有点不同。

但我想知道是否有人可以深入了解这里可能出了什么问题?我不知道它是否可能是文件服务器、Linux 内核、Python 中的某些东西,或者……好吧,完全是其他地方。

启用 rpcdebug 后,我们似乎得到:

Apr 24 11:58:47 build-2 kernel: NFS: release(lib/libgcc_s.so.1)
Apr 24 11:58:47 build-2 kernel: NFS: release(lib/libc.so.6)
Apr 24 11:58:47 build-2 kernel: NFS: release(locale/locale-archive)
Apr 24 11:58:47 build-2 kernel: NFS reply getattr: -512
Apr 24 11:58:47 build-2 kernel: nfs_revalidate_inode: (0:53/3834468196) getattr failed, error=-512
Apr 24 11:58:47 build-2 kernel: NFS: lookup(/python_race)
Apr 24 11:58:47 build-2 kernel: NFS call  lookup /python_race
Apr 24 11:58:47 build-2 kernel: RPC:       xs_tcp_send_request(168) = 0
Apr 24 11:58:47 build-2 kernel: NFS: release(bin/python3.11)

编辑:

还发现,如果您在 pool.join()

 之前添加 
terminate()
,则不会发生 

python linux nfs
1个回答
0
投票

这并不是一个真正的答案,而是确认它实际上是一个内核错误,而不是一个 python 问题 - 碰巧 python 是一种“触发”它的简单方法。

使用 RedHat 登录:https://issues.redhat.com/browse/RHEL-35853

如果有人遇到同样的问题,我们发现添加:
pool.join()

pool.terminate()
之前进入代码似乎阻止了它的发生,但考虑到问题是在内核空间中,我们不相信它比“只是”代码中的短暂延迟更实质性,这掩盖了隐式竞争状况。

我们发现,

sleep(0.05)
同样似乎可以防止这种情况发生,大概是出于类似的原因,因为用户空间不可能首先使目录条目缓存无效。

© www.soinside.com 2019 - 2024. All rights reserved.