使用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

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容