2014-10-16 5 views
9

나는 다중 처리 모듈을 사용하여 5 개의 다른 파이썬 프로세스를 생성하는 파이썬 프로세스를 가지고있다. 상위 프로세스 P0과 다른 프로세스 P1-P5를 호출 해 봅시다. 요구 사항은 P0에 SIGTERM을 보내면 먼저 P1에서 P5로 종료 한 다음 자체 종료해야한다는 것입니다.세마포어를 기다리는 동안 SIGTERM을받은 후 파이썬 프로세스가 어떻게 정상적으로 종료됩니까?

캐치는 P1과 P5가 세마포어를 기다리고 있습니다. 그래서 이러한 프로세스에 SIGTERM을 보내면 시그널 핸들러를 호출하고 종료합니다. 그러나 그들은 세마포어를 기다리고 있기 때문에 예외를 던집니다. 종료하기 전에 그 예외를 잡을 수있는 방법이 있습니까? P0에서 P5까지는 우아한 출구를 만들 수 있습니까?

역 추적 :

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

파이썬 2.7.8을 사용하고 있습니다. P1에서 P5까지는 프로세스간에 공유되는 큐에 액세스하려고 시도하며 세마포어를 사용하여 큐에 대한 액세스가 보호됩니다. 다음과 같은 의미로 사용됩니다. sem.acquire() item = q.get() sem.release() –

답변

13

당신은 다음 정상적으로 종료를 처리하기 위해 하위 프로세스에 잡힌 예외를 throw 신호 처리기를 설치할 수 있습니다.

다음은 서브 프로세스의 세마포어에서 대기하고 SIGTERM을 보내면 정상적으로 종료되는 스크립트의 예입니다. 이 서브 프로세스로부터 역 추적이없고 흐름을 보여줍니다

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

그 우아한 방식으로 서브 프로세스의 종료 :

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

이 스크립트의 예 실행은 다음과 같습니다. 이것은 SIGTERM이 프로세스 내에서 처리 될 수있는 정상적인 파이썬 예외를 던지는 서브 프로세스 시그널 핸들러에 의해 포착되기 때문입니다.