2014-10-16 3 views
9

Ich habe einen Python-Prozess, der 5 andere Python-Prozesse mit dem Multiprocessing-Modul hervorbringt. Lassen Sie uns den Elternprozess P0 und die anderen P1-P5 nennen. Wenn wir ein SIGTERM an P0 senden, muss es zuerst P1 bis P5 herunterfahren und sich dann selbst beenden.Wie wird ein Python-Prozess nach dem Empfang von SIGTERM beim Warten auf einen Semaphor ordnungsgemäß beendet?

Der Haken ist P1 und P5 warten auf Semaphoren. Wenn ich also SIGTERM an diese Prozesse sende, rufen sie den Signalhandler auf und beenden ihn. Aber da sie auf Semaphor warten, werfen sie eine Ausnahme. Gibt es eine Möglichkeit, diese Ausnahme vor dem Beenden zu fangen, so dass P0 bis P5 einen graziösen Ausgang ausführen können?

Traceback:

Traceback (most recent call last): 
    File "/usr/lib64/python2.7/multiprocessing/process.py", line 258, in _bootstrap 
Traceback (most recent call last): 
Process Process-2: 
    File "/usr/lib64/python2.7/multiprocessing/process.py", line 258, in _bootstrap 
Traceback (most recent call last): 
self.run() 
File "/usr/lib64/python2.7/multiprocessing/process.py", line 114, in run 
self._target(*self._args, **self._kwargs) 
Process Process-5: 
Traceback (most recent call last): 
File "/usr/lib64/python2.7/multiprocessing/process.py", line 258, in _bootstrap 
    self.run() 
File "/usr/lib64/python2.7/multiprocessing/process.py", line 114, in run 
    self._target(*self._args, **self._kwargs) 
File "/opt/fireeye/scripts/mip/StaticAnalysisRunner.py", line 45, in run 
    qsem.acquire() 
+0

Welche Version von Python verwenden Sie? Welchen spezifischen Anruf machen P1 und P5 eigentlich, die sie auf einen Semaphor warten lassen? Können Sie die Tracebacks einbeziehen? – dano

+1

Ein minimales Codebeispiel, das Ihr Problem reproduziert, wäre großartig. –

+0

Ich benutze Python 2.7.8 P1 bis P5 versuchen, auf eine Warteschlange über Prozesse freigegeben zugreifen und den Zugriff auf die Warteschlange ist mit einem Semaphor geschützt.Etwas wie folgt: sem.acquire() item = q.get() sem.release() –

Antwort

13

Sie können einen Signalhandler installieren, die eine Ausnahme auslöst, die dann in der subprocess gefangen Exits anmutig zu handhaben.

Hier ist ein Beispiel für ein Skript, das in einem Semaphor in einem Subprozess wartet und ordnungsgemäß beendet wird, wenn eine SIGTERM gesendet wird.

#!/usr/bin/env python 

import signal 
import time 
import multiprocessing 

class GracefulExit(Exception): 
    pass 


def signal_handler(signum, frame): 
    raise GracefulExit() 


def subprocess_function(): 
    try: 
     sem = multiprocessing.Semaphore() 
     print "Acquiring semaphore" 
     sem.acquire() 
     print "Semaphore acquired" 

     print "Blocking on semaphore - waiting for SIGTERM" 
     sem.acquire() 
    except GracefulExit: 
     print "Subprocess exiting gracefully" 


if __name__ == "__main__": 

    # Use signal handler to throw exception which can be caught to allow 
    # graceful exit. 
    signal.signal(signal.SIGTERM, signal_handler) 

    # Start a subprocess and wait for it to terminate. 
    p = multiprocessing.Process(target=subprocess_function) 
    p.start() 

    print "Subprocess pid: %d" % p.pid 

    p.join() 

Ein Beispiel Lauf dieses Skripts lautet wie folgt:

$ ./test.py 
Subprocess pid: 7546 
Acquiring semaphore 
Semaphore acquired 
Blocking on semaphore - waiting for SIGTERM 
----> Use another shell to kill -TERM 7546 
Subprocess exiting gracefully 

Es gibt keine Zurückverfolgungs vom subprocess ist und die Strömung zeigt, dass die subprocess Ausfahrten in einer anmutigen Art und Weise. Dies liegt daran, dass das SIGTERM vom Subprocess-Signalhandler abgefangen wird, der eine normale Python-Ausnahme auslöst, die innerhalb des Prozesses behandelt werden kann.