在研究了 python 守护进程之后,这个演练似乎是最可靠的:http://www.jejik.com/articles/2007/02/a_simple_unix_linux_daemon_in_python/
现在我正在尝试在守护程序类中实现一个工作池,我认为它正在工作(我没有彻底测试代码),除了在关闭时我得到一个僵尸进程。我已经阅读过我需要等待 child 的返回码,但我还不能确切地看到我需要怎么做。
下面是一些代码片段:
def stop(self):
...
try:
while 1:
self.pool.close()
self.pool.join()
os.kill(pid, SIGTERM)
time.sleep(0.1)
...
我在这里尝试了 os.killpg
和许多 os.wait
方法,但没有任何改进。我还在 os.kill
之前和之后玩过closing
/joining
池。这个循环就目前而言,永远不会结束,一旦它命中 os.kill
,我就会得到一个僵尸进程。 self.pool = Pool(processes=4)
出现在守护进程的 __init__
部分。在 start(self)
之后执行的 run(self)
中,我将调用 self.pool.apply_async(self.runCmd, [cmd, 10] , 回调=self.logOutput)
。但是,我想在调查之前先解决这个僵尸进程。
我怎样才能在守护进程中正确地实现池来避免这个僵尸进程?
最佳答案
如果不知道子/守护进程中发生了什么,就不可能对答案有 100% 的信心,但请考虑这是否可能。由于您的子进程中有工作线程,因此您实际上需要构建一些逻辑以在收到 SIGTERM 后加入所有这些线程。否则您的进程可能不会退出(即使退出也可能无法正常退出)。为此,您需要:
- 编写一个信号处理程序,用于捕获 SIGTERM 信号并为您的主线程触发事件的子/守护进程
- 在子/守护进程的主线程(非常重要)中安装信号处理程序
- SIGTERM 的事件处理程序必须向子/守护进程中的所有线程发出停止指令
- 所有线程在完成后都必须加入()(如果您假设 SIGTERM 会自动销毁所有内容,您可能也必须实现此逻辑)
- 一旦所有东西都加入并清理干净,你就可以退出主线程
如果您有用于 I/O 和各种事情的线程,那么这将是一件真正的苦差事。
此外,我通过实验发现,当您使用信号处理程序时,事件监听器的特定策略很重要。例如,如果您使用 select.select() ,则必须使用超时并在发生超时时重试;否则你的信号处理程序将不会运行。如果您有一个用于事件的 Queue.Queue 对象,并且您的事件监听器调用它的 .get() 方法,您必须使用超时,否则您的信号处理程序将不会运行。 (在 VM 中以 C 语言实现的“真正的”信号处理程序运行,但您的 Python 信号处理程序不会运行,除非您使用超时。)
祝你好运!
关于python - python多处理守护进程中的僵尸进程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6428842/