python multiprocessing Lock and Queue在较旧的Linux内核上不起作用

问题描述

我有一台实时计算机,运行32位linux,内核是4.9.124-rt94-rc1-mx6-sr + g79f5711,是由Yocto Project构建的。第二台运行32位linux并具有3.18.48-rt54-yocto-standard内核的较旧计算机也由Yocto Project创建。

我有2个简短的python脚本。 第一个

from multiprocessing import Queue,Lock

if __name__ == "__main__":
    flag_lock = Lock()
     
    flag_lock.acquire()
    flag_lock.release()

第二个:

import multiprocessing as mp
if __name__ == "__main__":
    test = mp.Queue()
    print("hello")
    test.put(3)
    print("world")

这两个脚本都可以在带有4.9.124-rt94-rc1-mx6-sr + g79f5711内核的较新机器上正常运行

在具有较旧内核的计算机上执行第一个脚本将引发异常:

回溯(最近通话最近): 文件“ ./temp_lock.py”,第8行,在 flag_lock.release() ValueError:信号量或锁释放了太多次

在具有较旧内核的计算机上执行第二个脚本将打印“ hello”,并将无限期地卡在test.put(3)上。

考虑到队列是线程安全的,我认为队列中的某些锁定机制会失败。

我使用python 3.6.0和python 3.8.3在两台计算机上执行此脚本的结果相同。

我在第一个脚本(带锁的脚本)上使用了strace,主要区别是在较旧的计算机上 ioctl(3,TCGETS,0xbfe94f4c)= -1 ENottY(设备不适当的ioctl)不断失败57次。

我还注意到调用了fstat64(),由此我得出结论,在多处理模块中植入锁是POSIX

解决方法

我用线程库替换了多处理库,现在解决了所有与锁定和队列有关的问题,并且代码在较旧的内核上执行的方式与在较新的内核上执行的方式相同。

我仍然无法解释到底是什么造成了什么不同,以及为什么multiprocessing.Queue和multiprocessing.Lock在较新的内核上可以正常工作,而在较旧的内核上却不能正常工作。