Linux 终止子进程

Linux 终止子进程,linux,python-3.x,pyqt4,subprocess,kill-process,Linux,Python 3.x,Pyqt4,Subprocess,Kill Process,我很好奇,为什么下面的代码会冻结。当我杀死python3解释器时,“cat”进程仍然是一个僵尸。我预计子进程将在主进程完成之前终止 当我将SIGTERM手动发送到cat/dev/zero时,该过程已正确完成(几乎立即完成) 我用不同的方法解决了这个问题,结果如下: 我必须用shell=False调用subprocess.Popen,因为否则它会创建2个进程(shell和进程),并且_cmd.kill()会向shell发送信号,而“进程”仍然是一个僵尸,正如您自己指出的,僵尸的原因是信号被shel

我很好奇,为什么下面的代码会冻结。当我杀死python3解释器时,“cat”进程仍然是一个僵尸。我预计子进程将在主进程完成之前终止

当我将SIGTERM手动发送到
cat/dev/zero
时,该过程已正确完成(几乎立即完成)


我用不同的方法解决了这个问题,结果如下:
我必须用shell=False调用subprocess.Popen,因为否则它会创建2个进程(shell和进程),并且_cmd.kill()会向shell发送信号,而“进程”仍然是一个僵尸,正如您自己指出的,僵尸的原因是信号被shell捕获,不会影响由它创建的进程。但是,有一种方法可以杀死shell及其创建的所有进程;您必须使用进程组功能。看看我说过的,如果你能在没有
shell=True的情况下管理,那总是更好的-看看我的答案。

我有一种模糊的感觉,你需要在杀死它之后调用
p.wait()
,来清理僵尸进程,但我不记得为什么了。太好了,它可以工作了!我将在周一上班时在受影响的机器上测试它。只需在run()函数的末尾添加self.quit()和在stop()函数的末尾添加self。谢谢你,汤玛西,不客气-很高兴听到我的直觉在现实中有一些根据。
#!/usr/bin/env python3
import subprocess
import re
import os
import sys
import time
from PyQt4 import QtCore

class Command(QtCore.QThread):
#    stateChanged = QtCore.pyqtSignal([bool])

    def __init__(self):
        QtCore.QThread.__init__(self)
        self.__runned = False
        self.__cmd = None
        print("initialize")

    def run(self):
        self.__runned = True

        self.__cmd = subprocess.Popen(["cat /dev/zero"], shell=True, stdout=subprocess.PIPE)
        try:
            while self.__runned:
                print("reading via pipe")
                buf = self.__cmd.stdout.readline()
                print("Buffer:{}".format(buf))
        except:
            logging.warning("Can't read from subprocess (cat /dev/zero) via pipe")
        finally:
            print("terminating")
            self.__cmd.terminate()
            self.__cmd.kill()

    def stop(self):
        print("Command::stop stopping")
        self.__runned = False
        if self.__cmd:
            self.__cmd.terminate()
            self.__cmd.kill()
            print("Command::stop stopped")


def exitApp():
    command.stop()
    time.sleep(1)
    sys.exit(0)


if __name__ == "__main__":
    app = QtCore.QCoreApplication(sys.argv)
    command = Command()
#    command.daemon = True
    command.start()
    timer = QtCore.QTimer()
    QtCore.QObject.connect(timer, QtCore.SIGNAL("timeout()"), exitApp)
    timer.start(2 * 1000)
    sys.exit(app.exec_())