Domanda

Sto avendo un problema strano con alcuni processi in esecuzione pitone utilizzando un processo cane da guardia.

Il processo di watchdog è scritto in Python ed è il genitore, ed ha una funzione chiamata start_child (nome) che usa subprocess.Popen per aprire il processo figlio. L'oggetto Popen è registrato in modo che il watchdog può monitorare il processo utilizzando poll () e poi finire con terminate () quando necessario. Se il bambino muore inaspettatamente, le chiamate watchdog start_child (nome) di nuovo e registra il nuovo oggetto Popen.

Ci sono 7 processi figli, che sono tutti anche pitone. Se corro nessuno dei figli manualmente, posso inviare SIGTERM o SIGINT utilizzando kill e ottenere i risultati mi aspetto (il processo termina).

Tuttavia, quando eseguito dal processo di watchdog, il bambino finirà solo dopo che il primo segnale. Quando il cane da guardia riavvia il bambino, il nuovo processo figlio non risponde più al SIGTERM o SIGINT. Non ho idea di che cosa sta causando questo.

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)

Quindi, quello che succede è watchdog.start () lancia tutti i 7 processi, e se io mando qualsiasi SIGTERM processo, finisce, e il thread di monitoraggio inizia di nuovo. Tuttavia, se poi inviare la nuova SIGTERM processo, l'ignora.

dovrei essere in grado di tenere l'invio di uccidere -15 ai processi rinnovate più e più volte. Perché ignorano dopo essere stato riavviato?

È stato utile?

Soluzione

Come spiegato qui: http://blogs.gentoo.org/agaffney/ 2005/03/18 / python_sucks , quando Python crea un nuovo thread, blocca tutti i segnali per quel filo (e per tutti i processi che genera filo).

Ho fissato questo usando sigprocmask, chiamato attraverso ctypes. Questo può o non può essere il modo "corretto" per farlo, ma funziona.

Nel processo figlio, durante __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

Altri suggerimenti

Non sarebbe meglio per ripristinare i gestori di segnale di default all'interno di Python, piuttosto che tramite ctypes? Nel vostro processo figlio, utilizzare il modulo di segnalazione:

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

RuntimeError viene generato quando si cerca di impostare segnali quali SIGKILL che non può essere catturato.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top