使用subprocess中Popen造成管道死锁问题排查记录

问题现象

在程序中使用了uwsgi的stats功能,使用Popen打开新的进程,执行:

uwsgi --connect-adn-read /home/tmp/stats

程序会在一段时间内发生假死。

分析与处理

被创建子进程在开始运行时,它的stdout, stderr已被重定向到管道里面了。Linux里的管道都会有一定的容量,当道管满了写执行write操作就会block,直到可以写为止。在上面的代码里,父进程创建子进程后,没有对它们通信的管道进行read操,而是调用 wait 等待子进程结束。如果子进程把输出写满了管道,那它会非常希望父进程尽快把它清理掉;而父进程此时在希望子进程尽快结束。
错误代码如下所示

process = Popen(args=emperor_arguments, stdout=PIPE, stderr=PIPE)
process.wait()

在python的Popen的官方文档中可以看到,推荐使用 Popen.communicate()。这个方法会把输出放在内存,而不是管道里,所以这时候上限就和内存大小有关了,一般不会有问题。而且如果要获得程序返回值,可以在调用 Popen.communicate() 之后取 Popen.returncode 的值。
修改后的代码如下:

process = Popen(args=emperor_arguments, stdout=PIPE, stderr=PIPE)    
stdoutdata, stderrdata = process.communicate()

经测试问题已经处理。

参考资料

https://blog.csdn.net/linyt/article/details/2983960

你可能感兴趣的:(使用subprocess中Popen造成管道死锁问题排查记录)