记用C++调用Python函数时遇到的一个死锁
在用C++代码调用Python模块中的一个函数时,程序在Python的某一行代码处挂住不动,经过摸索后,找到了Python挂住的那一行代码,又经过一阵摸索后,找到了挂住的原因,最后通过修改Python代码解决了这个问题。
- 寻找挂住的Python代码行:
不断的加print
函数,或者使用logging
模块打日志。之后发现挂在代码的enumerate()
处。 - 寻找挂住的原因:
- 使用
gdb attach pid_value
查看挂住时候的C函数调用栈,发现栈顶是
#0 futex_wait (val=72, addr=0x7f1a4c020744) at /opt/conda/conda-bld/compilers_linux-64_1520532893746/work/.build/src/gcc-7.2.0/libgomp/config/linux/x86/futex.h:44
也就是说,程序死锁了。 - 编写Python的测试脚本,发现可以跑通。然后使用pdb对Python测试文件进行调试,逐行运行后发现,
enumerate()
针对的对象的源代码中使用了multiprocessing
。
- 使用
- 分析
multiprocess
会用到GIL,这在纯Python程序运行中不会有问题,但是在使用C++调用Python的函数时,C++程序首先必须要获取Python的GIL,这导致在后面使用multiprocessing
时会出现一直等GIL的情况。 - 解决
经过对代码的进一步分析发现,可以换用其他不使用enumerate()
的办法。主要是跳过multiprocessing
。更改后成功通过测试。
总结
在Python的
multiprocessing
需要用到GIL。这点在编写C/C++调用Python的代码中需要注意
参考链接:
gdb attach到已经存在的进程进行在线调试------能获取当前栈的所有变量值!
gdb attach使用
multiprocessing