蟒过程被重新启动后停止响应SIGTERM / SIGINT
题
我在与一些蟒过程中利用看门狗进程中运行一个奇怪的问题。
看门狗过程是写在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上升。