Python Processes는 다시 시작한 후 Sigterm / Sigint에 대한 응답을 중지합니다.

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

  •  16-09-2019
  •  | 
  •  

문제

Watchdog 프로세스를 사용하여 실행하는 일부 파이썬 프로세스에 이상한 문제가 있습니다.

Watchdog 프로세스는 Python으로 작성되었으며 부모이며 기능이 있습니다. start_child (이름) 사용하는 하위 프로세스 .popen 아동 과정을 열기 위해. Popen 객체는 워치 독이 사용 프로세스를 모니터링 할 수 있도록 기록됩니다. 투표() 결국에는 끝납니다 끝내다() 필요할 때. 아이가 예기치 않게 죽으면 워치 독이 전화를 겁니다 start_child (이름) 다시 새로운 Popen 객체를 녹음합니다.

7 개의 아동 프로세스가 있으며,이 과정은 모두 파이썬입니다. 어린이 중 하나를 수동으로 운영하면 Sigterm 또는 Sigint를 사용하여 보낼 수 있습니다. 죽이다 그리고 내가 기대하는 결과를 얻습니다 (프로세스 끝).

그러나 워치 독 과정에서 달리면 아이는 첫 번째 신호. Watchdog이 아이를 다시 시작하면 새로운 아동 과정이 더 이상 Sigterm 또는 Sigint에 응답하지 않습니다. 나는 이것을 원인하는 것이 무엇인지 전혀 모른다.

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)

그래서 무슨 일이 일어나는지 Watchdog.start () 7 개의 프로세스를 모두 시작하고 프로세스 sigterm을 보내면 종료되고 모니터 스레드가 다시 시작됩니다. 그러나 새로운 프로세스를 보내면 Sigterm을 보내면 무시합니다.

다시 시작된 프로세스에 -15를 계속해서 킬을 보낼 수 있어야합니다. 다시 시작한 후 무시하는 이유는 무엇입니까?

도움이 되었습니까?

해결책

여기에 설명 된대로 : http://blogs.gentoo.org/agaffney/2005/03/18/python_sucks , Python이 새 스레드를 생성하면 해당 스레드 (및 스레드가 생성되는 모든 프로세스의 경우)에 대한 모든 신호를 차단합니다.

CTYPES를 통해 불리는 SIGPROCMASK를 사용하여 이것을 수정했습니다. 이것은 "올바른"방법 일 수도 있고 아닐 수도 있지만 작동합니다.

어린이 과정에서 __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

다른 팁

CTypes가 아닌 Python 내에서 기본 신호 핸들러를 복원하는 것이 더 낫지 않습니까? 자녀 프로세스에서 신호 모듈을 사용하십시오.

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

RuntimeError는 잡을 수없는 Sigkill과 같은 신호를 설정하려고 할 때 발생합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top