【发布时间】:2009-07-15 20:11:48
【问题描述】:
我遇到了一些使用看门狗进程运行的 python 进程的奇怪问题。
看门狗进程是用python编写的,是父进程,有一个名为start_child(name)的函数,它使用subprocess.Popen打开子进程。记录 Popen 对象,以便看门狗可以使用 poll() 监视进程,并最终在需要时使用 terminate() 结束它。 如果孩子意外死亡,看门狗会再次调用 start_child(name) 并记录新的 Popen 对象。
有7个子进程,都是python。如果我手动运行任何子进程,我可以使用 kill 发送 SIGTERM 或 SIGINT 并获得我期望的结果(进程结束)。
但是,当从看门狗进程运行时,子进程只会在 FIRST 信号之后结束。当看门狗重新启动子进程时,新的子进程不再响应 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,它会忽略它。
我应该能够一遍又一遍地向重新启动的进程发送 kill -15 。为什么重启后就忽略了?
【问题讨论】:
-
所以这似乎是由在 python 线程中弹出一个进程引起的。根据blogs.gentoo.org/agaffney/2005/03/18/python_sucks,Python 设置了一个信号掩码来阻止从线程启动的进程上的所有信号。什么鬼,蟒蛇?我现在正在尝试使用 ctypes 调用 sigprocmask() 并将信号掩码重置为不阻塞。