Processes started with Python subprocess module are not killed when app exits

soneedu

When I exit my application (code below), the two ping processes I start using subprocess.Popen are not automatically killed, and still show up in the Windows 7 task list.

While the app is running, the ping processes show up under Python.exe as two threads. When the app exits, these two processes move to the system process tab and keep running there.

How can I fix this? I want the two ping processes to be killed when my application is closed.

# -*- coding: utf-8 -*- 

import sys 
import time 
import subprocess 
from threading import Thread 
import re 
from PyQt4.QtGui import QMainWindow, QApplication, QStandardItemModel, QStandardItem, QWidget, QVBoxLayout, QTableView 
from PyQt4.QtCore import pyqtSignature, Qt, QTimer, SIGNAL, QString, QMetaObject 
from Queue import Queue 

try: 
    _fromUtf8 = QString.fromUtf8 
except AttributeError: 
    _fromUtf8 = lambda s: s 

class Ui_MainWindow(object): 
    def setupUi(self, MainWindow): 
        MainWindow.setObjectName(_fromUtf8("MainWindow")) 
        MainWindow.resize(500, 435) 
        self.centralWidget = QWidget(MainWindow) 
        self.centralWidget.setObjectName(_fromUtf8("centralWidget")) 
        self.verticalLayout = QVBoxLayout(self.centralWidget) 
        self.verticalLayout.setObjectName(_fromUtf8("verticalLayout")) 
        self.tableView = QTableView(self.centralWidget) 
        self.tableView.setObjectName(_fromUtf8("tableView")) 
        self.verticalLayout.addWidget(self.tableView) 
        MainWindow.setCentralWidget(self.centralWidget) 

        self.retranslateUi(MainWindow) 
        QMetaObject.connectSlotsByName(MainWindow) 

    def retranslateUi(self, MainWindow): 
        MainWindow.setWindowTitle(QApplication.translate("MainWindow", "Ping Tester", None, QApplication.UnicodeUTF8)) 

if sys.platform.startswith('linux'): 
    getdata = re.compile(r"icmp_req=(\d+) ttl=(\d+) time=([\d\.]+)\sms") 
    pingstr = ["ping", "-n", "-i 0.2"] 
    filtered = "Packet filtered" 
    delaytime = 200 
else: 
    getdata = re.compile(r"=([\d\.]+)ms TTL=(\d+)") 
    pingstr = ["ping.exe", "-t"] 
    timeout = "Request timed out." 
    delaytime = 500 

try: 
    with open("ips.conf", "r") as f: 
        t_node = f.read().decode('utf-8') 
        if not t_node: 
            raise IOError 
except IOError: 
    with open("ips.conf", "w") as f: 
        t_node = u""" 
        8.8.8.8-Google 
        184.22.112.34-USAHE 
        """ 
        f.write(t_node.encode('utf-8')) 

node = [] 
for line in t_node.split('\n'): 
    try: 
        ip, desc = line.strip().split("-") 
        node.append((ip, desc)) 
    except ValueError: 
        pass 
nodecount = len(node) 

class MainWindow(QMainWindow, Ui_MainWindow): 
    """ 
    Class documentation goes here. 
    """ 
    def __init__(self, parent = None): 
        """ 
        Constructor 
        """ 
        QMainWindow.__init__(self, parent) 
        self.setupUi(self) 
        self.model = QStandardItemModel() 
        self.model.setColumnCount(6) 
        self.model.setRowCount(nodecount) 
        self.model.setHorizontalHeaderLabels(["IP", "Description", "Loss%", "CurPing", "AvgPing", "TTL"]) 
        for i, (ip, desc) in enumerate(node): 
            self.setitem(i, 0, ip) 
            self.setitem(i, 1, desc) 
            self.setitem(i, 2, "") 
            self.setitem(i, 3, "") 
            self.setitem(i, 4, "") 
            self.setitem(i, 5, "") 
        self.tableView.setModel(self.model) 
        for i in range(len(node)): 
            self.tableView.setRowHeight(i, 18) 
        self.resizetable() 
        self.timer = QTimer(self) 
        self.connect(self.timer, 
                     SIGNAL("timeout()"), 
                     self.checkitems) 
        self.timer.start(delaytime) 

    def checkitems(self): 
        while not q.empty(): 
            item = q.get() 
            self.chgtxt(*item) 
            q.task_done() 
        self.resizetable() 

    def resizetable(self): 
        self.tableView.resizeColumnsToContents() 

    def chgtxt(self, x, y, value): 
        self.model.item(x, y).setText(value) 

    def setitem(self, x, y, value): 
        self.model.setItem(x, y, QStandardItem(value)) 

app = QApplication(sys.argv) 
ui = MainWindow() 
ui.show() 
q = Queue() 

def pinger(i, ip, desc): 
    s = "" 
    avgping = 0 
    count = 0 
    timeoutcount = 0 
    ret = subprocess.Popen(pingstr + [ip], 
                            stdout=subprocess.PIPE) 
    while True: 
        try: 
            s += ret.stdout.read(1) 

            tryfind = getdata.findall(s) 
            if sys.platform.startswith('linux'): 
                if len(tryfind) > 0: 
                    req, ttl, crtping = tryfind[-1] 
                    avgping += float(crtping) 
                    count += 1 
                    q.put((i, 3, crtping + "ms")) 
                    q.put((i, 4, "%.2f" % (avgping * 1.0 / count) + "ms")) 
                    q.put((i, 5, ttl)) 
                    q.put((i, 2, "%.2f" % ((int(req) - count) * 100.0 / int(req)))) 
                    s = "" 
                elif filtered in s: 
                    q.put((i, 2, "Failed")) 
                    q.put((i, 3, "Failed")) 
                    q.put((i, 4, "Failed")) 
                    q.put((i, 5, "Failed")) 
                    ret.kill() 
                    s = "" 
            else: 
                if len(tryfind) > 0: 
                    crtping, ttl = tryfind[-1] 
                    avgping += float(crtping) 
                    count += 1 
                    q.put((i, 3, crtping + "ms")) 
                    q.put((i, 4, "%.2f" % (avgping * 1.0 / count) + "ms")) 
                    q.put((i, 5, ttl)) 
                    q.put((i, 2, "%.2f" % (timeoutcount * 100.0 / (count + timeoutcount)))) 
                elif timeout in s: 
                    timeoutcount += 1 
                    q.put((i, 2, "-")) 
                    q.put((i, 3, "-")) 
                    if count: 
                        q.put((i, 5, "%.2f" % (timeoutcount * 100.0 / (count + timeoutcount)))) 
                    else: 
                        q.put((i, 5, "-")) 
                    s = "" 
        except IOError: 
            print s 
            break 

def startworkers(): 
    for i, (ip, desc) in enumerate(node): 
        worker = Thread(target=pinger, args=(i, ip, desc)) 
        worker.setDaemon(True) 
        worker.start() 
        time.sleep(delaytime / 10000.0) 

startthread = Thread(target=startworkers) 
startthread.setDaemon(True) 
startthread.start() 

sys.exit(app.exec_())  
dano

Here's a way you can do it, using atexit:

import subprocess
from threading import Thread
import sys 
import atexit

from PyQt4.QtGui import QMainWindow, QApplication

class Ui_MainWindow(object): 
    def setupUi(self, MainWindow): 
        MainWindow.setObjectName(("MainWindow")) 
        MainWindow.resize(500, 435) 

def runproc():
    p = subprocess.Popen(["sleep", "500"])
    atexit.register(kill_proc, p)
    p.communicate()

def kill_proc(proc):
    try:
        proc.terminate()
    except Exception:
        pass

class MainWindow(QMainWindow):
    def __init__(self):
        QMainWindow.__init__(self)
        self.resize(300, 300)

if __name__ == "__main__":
    app = QApplication(sys.argv)
    ui = MainWindow()
    ui.show()
    for i in range(0, 3): 
        t = Thread(target=runproc)
        t.start()
    sys.exit(app.exec_())

Each thread registers an atexit callback, which passes the Popen object it created. When the process exits via normal means, the atexit handlers get called, and in each one we call terminate on the Popen object, which kills the process. Note that this does not handle someone sending a signal like SIGKILL to your process; it only handles it being exited by closing the QMainWindow, or something doing something like Ctrl+C if you're running via the CLI.

Edit:

To handle the exception you get on shutdown, you have to change how your code handles the data it reads from stdout of the subprocesses. When you kill the subprocesses at shutdown, they sends None to their stdout, and your thread tries to process that None as if it was actual data. You just need to handle that case gracefully:

out = ret.stdout.read(1)
if not out:
    break
s += out 
print s
tryfind = getdata.findall(s)

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

From Dev

Processes started with Python subprocess module are not killed when app exits

From Dev

Systemd and process spawning: child processes are killed when main process exits

From Dev

Systemd and process spawning: child processes are killed when main process exits

From Dev

How can I prevent new instances of background processes when calling adb in python subprocess module

From Dev

Connect two processes started with asyncio.subprocess.create_subprocess_exec()

From Dev

psutil/subprocess return code when process killed

From Dev

psutil/subprocess return code when process killed

From Dev

Erlang VM killed when creating millions of processes

From Dev

Stopping FSSM processes when ruby exits

From Dev

ContentObserver registered in service is killed when app killed

From Dev

SBT to run Play app exits immediately when started using scala.sys.process.run?

From Dev

Spawn a subprocess in foreground, even after python exits

From Dev

Detecting if a process exits cleanly with Python subprocess

From Dev

When a Python process is killed on OS X, why doesn't it kill the child processes?

From Dev

Callback when App is killed by swiping

From Dev

SharedPreferences deleted when the app is killed

From Dev

Android geofencing when app is killed

From Dev

Geofences not working when app is killed

From Dev

Callback when App is killed by swiping

From Dev

Delete Keychain when app is killed

From Dev

Python subprocess module and PIPE

From Dev

subprocess module in python

From Dev

subprocess module on python FileNotFoundError

From Dev

Monitor the number of processes spawned by subprocess in python

From Dev

when parent process is killed by 'kill -9', how to terminate child processes

From Dev

subprocess checkout error only when service is not started

From Dev

Django-cities exits with "killed"

From Dev

Django-cities exits with "killed"

From Dev

How to install subprocess module for python?

Related Related

  1. 1

    Processes started with Python subprocess module are not killed when app exits

  2. 2

    Systemd and process spawning: child processes are killed when main process exits

  3. 3

    Systemd and process spawning: child processes are killed when main process exits

  4. 4

    How can I prevent new instances of background processes when calling adb in python subprocess module

  5. 5

    Connect two processes started with asyncio.subprocess.create_subprocess_exec()

  6. 6

    psutil/subprocess return code when process killed

  7. 7

    psutil/subprocess return code when process killed

  8. 8

    Erlang VM killed when creating millions of processes

  9. 9

    Stopping FSSM processes when ruby exits

  10. 10

    ContentObserver registered in service is killed when app killed

  11. 11

    SBT to run Play app exits immediately when started using scala.sys.process.run?

  12. 12

    Spawn a subprocess in foreground, even after python exits

  13. 13

    Detecting if a process exits cleanly with Python subprocess

  14. 14

    When a Python process is killed on OS X, why doesn't it kill the child processes?

  15. 15

    Callback when App is killed by swiping

  16. 16

    SharedPreferences deleted when the app is killed

  17. 17

    Android geofencing when app is killed

  18. 18

    Geofences not working when app is killed

  19. 19

    Callback when App is killed by swiping

  20. 20

    Delete Keychain when app is killed

  21. 21

    Python subprocess module and PIPE

  22. 22

    subprocess module in python

  23. 23

    subprocess module on python FileNotFoundError

  24. 24

    Monitor the number of processes spawned by subprocess in python

  25. 25

    when parent process is killed by 'kill -9', how to terminate child processes

  26. 26

    subprocess checkout error only when service is not started

  27. 27

    Django-cities exits with "killed"

  28. 28

    Django-cities exits with "killed"

  29. 29

    How to install subprocess module for python?

HotTag

Archive