Linux下Python多进程共享内存偶发FileNotFoundError求助
我正在为Python应用创建共享内存,供父进程及其派生的子进程使用。多数情况下运行正常,但偶发如下报错栈:
Traceback (most recent call last):
File "", line 1, in
File "/usr/lib/python3.8/multiprocessing/spawn.py", line 116, in spawn_main
exitcode = _main(fd, parent_sentinel)
File "/usr/lib/python3.8/multiprocessing/spawn.py", line 126, in _main
self = reduction.pickle.load(from_parent)
File "/usr/lib/python3.8/multiprocessing/synchronize.py", line 110, in setstate
self._semlock = _multiprocessing.SemLock._rebuild(*state)
FileNotFoundError: [Errno 2] No such file or directory: '/psm_47f7f5d7'
需说明的是,我们的代码99%场景正常。作为7×24运行的服务进程,我们会定期为每个新派生进程创建新共享内存,仅偶尔出现上述错误导致应用崩溃。
更新:发现问题主要出现在应用运行一段时间后,启动初期创建共享内存和派生进程均正常。
共享内存创建代码如下:
# Spawn context for multiprocessing _mp_spawn_ctxt = multiprocessing.get_context("spawn") _mp_spawn_ctxt_pipe = _mp_spawn_ctxt.Pipe # Create shared memory mem_size = width * height * bpp shared_mem = shared_memory.SharedMemory(create=True, size=mem_size) image = np.ndarray((height, width, bpp), dtype=np.uint8, buffer=shared_mem.buf) parent_pipe, child_pipe = _mp_spawn_ctxt_pipe() time.sleep(0.1) # Spawn new process # _CameraProcess is a custom class derived from _mp_spawn_ctxt.Process proc = _CameraProcess(shared_mem, child_pipe) proc.start()
可能的原因及分析
共享内存对象被提前回收:在spawn模式下,子进程启动时会重新导入代码并通过pickle反序列化父进程传递的对象。如果父进程中
shared_mem对象的引用计数过早降到0(比如被垃圾回收),系统会自动删除对应的共享内存文件(/psm_xxx),此时子进程反序列化时就会找不到文件。运行一段时间后,Python的GC机制可能更频繁触发,导致这个问题概率上升。Pipe对象与共享内存的同步问题:你加了
time.sleep(0.1)试图同步,但这是不可靠的。spawn子进程启动需要时间,可能在子进程还没完成反序列化时,父进程中的某些资源就被意外释放。尤其是长期运行后,系统负载变化会让进程启动时间波动,固定时长的sleep不再足够。系统共享内存资源耗尽:长期运行不断创建共享内存,若没有正确关闭和释放旧的共享内存对象,系统
/dev/shm目录下的psm_*共享内存文件会堆积。当资源接近耗尽时,新创建的共享内存可能被系统强制清理,或者创建时出现隐性错误,导致子进程无法找到对应的文件。pickle反序列化的时序问题:在spawn模式下,子进程会先初始化自身环境,再反序列化父进程传递的参数。如果
_CameraProcess的初始化代码中过早尝试访问共享内存,而此时共享内存文件还没完成在子进程中的映射,也可能触发找不到文件的错误,这种情况多为偶发的时序冲突。
内容的提问来源于stack exchange,提问作者Matthias

