Python Prozesse reagieren nicht mehr auf SIGTERM / SIGINT nach neu gestartet werden

StackOverflow https://stackoverflow.com/questions/1133693

  •  16-09-2019
  •  | 
  •  

Frage

Ich habe ein seltsames Problem mit einigen Python laufenden Prozesse einen Watchdog-Prozess.

Der Watchdog-Prozess ist in Python geschrieben und ist die Mutter und hat eine Funktion namens start_child (name) , welche verwendet subprocess.Popen das Kind Prozess zu öffnen. Die Popen Aufgabe wird aufgezeichnet, so dass der Watchdog den Prozess überwachen kann mit poll () und es schließlich mit terminate () , wenn nötig. Wenn das Kind unerwartet stirbt, die Watchdog-Anrufe start_child (name) wieder und zeichnet das neue Popen Objekt.

Es gibt 7 Child-Prozesse, von denen alle sind auch Python. Wenn ich alle Kinder manuell ausführen, kann ich SIGTERM oder SIGINT senden mit töten und die Ergebnisse erhalten, erwarte ich (der Prozess endet).

Wenn jedoch von dem Watchdog-Prozess ausgeführt wird, wird das Kind nur am Ende nach dem FIRST Signal. Wenn der Watchdog das Kind neu gestartet wird, reagiert der neue Kind-Prozess nicht mehr SigTerm oder SIGINT. Ich habe keine Ahnung, was das verursacht.

watchdog.py

class watchdog:
    # <snip> various init stuff

    def start(self):
        self.running = true

        kids = ['app1', 'app2', 'app3', 'app4', 'app5', 'app6', 'app7']
        self.processes = {}

        for kid in kids:
            self.start_child(kid)

        self.thread = threading.Thread(target=self._monitor)
        self.thread.start()

        while self.running:
            time.sleep(10)

    def start_child(self, name):
        try:
            proc = subprocess.Popen(name)
            self.processes[name] = proc
        except:
            print "oh no"
        else:
            print "started child ok"

    def _monitor(self):
        while self.running:
            time.sleep(1)
            if self.running:
                for kid, proc in self.processes.iteritems():
                    if proc.poll() is not None: # process ended
                        self.start_child(kid)

Also, was passiert ist watchdog.start () startet alle 7 Prozesse, und wenn ich jeden Prozess SIGTERM senden, es endet, und der Monitor-Thread geht es wieder los. Allerdings, wenn ich dann den neuen Prozess SIGTERM senden, ignoriert es.

soll ich in der Lage sein, das Senden zu halten kill -15 den Neustart Prozesse immer und immer wieder. Warum ignorieren sie es nach dem Neustart zu werden?

War es hilfreich?

Lösung

Wie hier erklärt: http://blogs.gentoo.org/agaffney/ 2005/03/18 / python_sucks , wenn Python erstellt einen neuen Thread, blockiert es alle Signale für diesen Thread (und für alle Prozesse, die Thread-Spawns).

Ich reparierte diese mit sigprocmask, genannt durch ctypes. Dies kann oder kann nicht die „richtige“ Art und Weise, es zu tun, aber es funktioniert.

In dem untergeordneten Prozess, während __init__:

libc = ctypes.cdll.LoadLibrary("libc.so")
mask = '\x00' * 17 # 16 byte empty mask + null terminator 
libc.sigprocmask(3, mask, None) # '3' on FreeBSD is the value for SIG_SETMASK

Andere Tipps

Wäre es nicht besser sein, die Standard Signal-Handler in Python wiederherstellen anstatt über ctypes? In Ihrem Kind Prozess, verwenden Sie das Signalmodul:

import signal
for sig in range(1, signal.NSIG):
    try:
        signal.signal(sig, signal.SIG_DFL)
    except RuntimeError:
        pass

Runtime angehoben wird, wenn sie versuchen Signale zu setzen, wie SIGKILL, die nicht gefangen werden kann.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top