0

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

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

#!/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_())
4

2 回答 2

2

正如您自己指出的那样,僵尸的原因是信号被shell捕获并且不影响它创建的进程。但是有一种方法可以杀死 shell 及其创建的所有进程;您必须使用进程组功能。请参阅如何终止使用 shell=True 启动的 python 子进程话虽如此,如果您可以在没有它的情况下进行管理,shell=True那总是可取的 - 请参阅我的答案here

于 2012-10-22T09:14:07.473 回答
0

我以不同的方式解决了这个问题,所以结果如下:我必须使用 shell=False 调用 subprocess.Popen,因为否则它会创建 2 个进程(shell 和进程)并且 __cmd.kill() 在 "进程”仍然是僵尸

于 2012-08-08T14:15:27.383 回答