我在与一些蟒过程中利用看门狗进程中运行一个奇怪的问题。

看门狗过程是写在Python和是父,并且具有所谓的 start_child(名称)它使用的 subprocess.Popen 打开子进程的功能。所述POPEN对象被记录,使得可以看门狗监视使用的轮询()过程并最终与结束它的终止()需要时。 如果孩子意外死亡,看门狗调用的 start_child(名称)的再次并记录新POPEN对象。

有7个的子进程,所有这些也蟒。如果我手动运行任何的孩子,我可以使用的的发送SIGTERM或SIGINT得到我期望的结果(过程结束)。

然而,从看门狗进程中运行时,孩子就会仅在第一信号之后结束。当看门狗重启的孩子,新的子进程不再响应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中创建一个新的线程,它的块的所有信号为该线程(以及任何进程线程产卵)。

我固定此使用sigprocmask,通过ctypes的调用。这可能是也可能不是“正确”的方式做到这一点,但它确实工作。

在子进程,__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

其他提示

那岂不是更好的Python之内,而不是通过ctypes的恢复默认的信号处理程序?在你的子进程,使用信号模块:

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

试图设置信号,例如其SIGKILL不能被捕获时RuntimeError上升。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top