问题现象
在程序中使用了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()
经测试问题已经处理。
网友评论