我有一个 Python 守护程序在生产中运行。它使用 7 到 120 个线程。最近最小的实例(7 个线程)开始出现挂起,而所有其他实例从未出现过此类问题。将 strace 附加到 python 进程表明所有线程都在调用 futex FUTEX_WAIT_PRIVATE,因此它们可能正在尝试锁定某些东西。
你将如何调试这样的问题?
请注意,这是一个从闪存运行的生产系统,因此磁盘写入也受到限制。
我有一个 Python 守护程序在生产中运行。它使用 7 到 120 个线程。最近最小的实例(7 个线程)开始出现挂起,而所有其他实例从未出现过此类问题。将 strace 附加到 python 进程表明所有线程都在调用 futex FUTEX_WAIT_PRIVATE,因此它们可能正在尝试锁定某些东西。
你将如何调试这样的问题?
请注意,这是一个从闪存运行的生产系统,因此磁盘写入也受到限制。
观察有点不正确。一个线程没有调用 futex,而是在持有 gil 的同时进行交换。由于所讨论的机器是低硬件,因此这种交换花费了很长时间并且似乎是一个死锁。根本问题是内存泄漏。:-(
亲爱的 Helmut,我在 FUTEXT_WAIT_PRIVATE 上挂着一个线程时遇到了同样的问题。
看来你已经解决了这个问题。您能否分享有关该解决方案的更多信息?
升级版:
锁的原因终于找到了(至少对我来说是这样):这是由于Python中的导入锁。
考虑以下情况:
文件1.py:
导入文件2
文件2.py:
创建线程“thread2”
运行“线程2”
等到“thread2”完成某个函数(比如说go Go())
定义去():
导入一些模块
……
在这里,Go() 中的导入将挂起,因为导入被锁定在主线程中(通过 import file2),在 Go() 完成之前不会释放。用户将在 strace 中看到 FUTEX_WAIT_PRIVATE 挂起。
为了解决这个问题,在将 file2 导入 Do() 函数期间执行的代码并在导入 file2 后运行它:
导入文件2
文件 2.Do()