Python 在 futex 调用中挂起
我有一个在生产环境中运行的Python守护进程。它使用的线程数量在7到120之间。最近,最小的实例(7个线程)开始出现卡顿的情况,而其他实例从来没有出现过这种问题。通过给Python进程附加strace工具,可以看到所有线程都在调用futex FUTEX_WAIT_PRIVATE,这说明它们可能在尝试锁定某些东西。
你会怎么调试这样的问题呢?
需要注意的是,这是一个从闪存运行的生产系统,所以磁盘写入也受到限制。
2 个回答
2
亲爱的Helmut,我也遇到了一个线程在FUTEXT_WAIT_PRIVATE上挂起的问题。
看起来你已经解决了这个问题。能不能分享一下你的解决办法呢?
更新:
我最终找到了锁住的原因(至少在我的情况下):是因为Python中的导入锁。
考虑以下情况:
file1.py:
导入 file2
file2.py:
创建线程 "thread2"
运行 "thread2"
等待 "thread2" 完成某个函数(我们称之为 Go())
定义 Go() 函数:
导入 some_module
....
在这里,Go() 函数中的导入会挂起,因为在主线程中(通过导入 file2)锁住了导入,这个锁要等到 Go() 完成后才能释放。用户会在 strace 中看到挂在 FUTEX_WAIT_PRIVATE 上。
为了解决这个问题,可以把在导入 file2 时执行的代码放到 Do() 函数中,然后在导入 file2 后运行它:
导入 file2
file2.Do()
5
这个观察有点不太准确。其实有一个线程并没有调用futex,而是一直在持有全局解释器锁(gil)的时候进行交换。由于这台机器的硬件比较差,这个交换过程花了很长时间,看起来就像是死锁一样。根本的问题是内存泄漏。:-(