2012-06-07 97 views
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_()) 
+0

我有一個模糊的感覺,你需要在殺死它之後調用'p.wait()'來清理殭屍進程,但我不記得原因。 –

+0

太棒了,它的工作原理!我將在星期一的工作中在受影響的機器上測試它。只需在run()函數的末尾添加self.quit(),並在stop()函數的末尾添加self .__ cmd.wait(),就可以正確完成並且不會留下殭屍。謝謝Thomas – Miso

+0

不客氣 - 很高興聽到我的預感在現實中有了一些基礎。 –

回答

0

我以不同的方式解決了這個問題,所以這裏的結果: 我要打電話subprocess.Popen shell = False,否則它會創建2個進程(shell和進程)和__cmd.kill()向shell發送信號,而「process」仍然是殭屍

2

正如你自己所說的,殭屍的原因是信號被外殼捕獲並且不影響由它創建的過程。但是有一種方法可以殺死shell以及由它創建的所有進程;您必須使用進程組功能。請參閱How to terminate a python subprocess launched with shell=True話雖如此,如果您可以在沒有shell=True的情況下進行管理,那總是可取的 - 請參閱我的回答here

+0

這可能是有用的,謝謝! – Miso