2014-10-16 3 views
9

У меня есть процесс Python, который порождает 5 других процессов Python с использованием модуля многопроцессорности. Назовем родительский процесс P0 и другие P1-P5. Требование состоит в том, что если мы отправляем SIGTERM в P0, он должен сначала выключить P1-P5, а затем выйти.Как процесс python изящно выходит после получения SIGTERM, ожидая семафора?

Уловка P1 и P5 ждут семафоров. Поэтому, когда я посылаю SIGTERM для этих процессов, они вызывают обработчик сигнала и выходят. Но поскольку они ждут семафора, они бросают исключение. Есть ли способ поймать это исключение перед выходом, чтобы P0-P5 мог сделать изящный выход?

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

Какую версию Python вы используете? Каким конкретным вызовом являются P1 и P5, которые действительно заставляют их ждать семафора? Можете ли вы включить трассировки? – dano

+1

Минимальный образец кода, воспроизводящий вашу проблему, был бы замечательным. –

+0

Я использую Python 2.7.8 P1 to P5 пытаются получить доступ к очереди, разделяемой всеми процессами, и доступ к очереди защищен с помощью семафора. Что-то вроде этого: sem.acquire() item = q.get() sem.release() –

ответ

13

Вы можете установить обработчик сигнала, который генерирует исключение, которое затем попавшие в подпроцессе для обработки выходов изящно.

Ниже приведен пример сценария, который ждет семафора в подпроцессе и изящно прекращается при отправке SIGTERM.

#!/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() 

Пример выполнения этого сценария заключается в следующем:

$ ./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 

Там нет отслеживающий из подпроцесса и поток показывает, что подпроцесс завершается в изящным образом. Это связано с тем, что SIGTERM улавливается обработчиком сигнала подпроцессора, который генерирует обычное исключение Python, которое может обрабатываться внутри процесса.

Смежные вопросы