Linux 如何杀死多处理模块创建的僵尸进程?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/19322129/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-07 01:03:33  来源:igfitidea点击:

how to kill zombie processes created by multiprocessing module?

pythonlinuxmultithreading

提问by Vor

I'm very new to multiprocessingmodule. And I just tried to create the following: I have one process that's job is to get message from RabbitMQ and pass it to internal queue (multiprocessing.Queue). Then what I want to do is : spawn a process when new message comes in. It works, but after the job is finished it leaves a zombie process not terminated by it's parent. Here is my code:

我对multiprocessing模块很陌生。我只是尝试创建以下内容:我有一个进程的工作是从 RabbitMQ 获取消息并将其传递给内部队列 ( multiprocessing.Queue)。然后我想要做的是:当新消息进来时产生一个进程。它可以工作,但在工作完成后,它会留下一个僵尸进程,而不是被它的父进程终止。这是我的代码:

Main Process:

主要流程:

 #!/usr/bin/env python

 import multiprocessing
 import logging
 import consumer
 import producer
 import worker
 import time
 import base

 conf = base.get_settings()
 logger = base.logger(identity='launcher')

 request_order_q = multiprocessing.Queue()
 result_order_q = multiprocessing.Queue()

 request_status_q = multiprocessing.Queue()
 result_status_q = multiprocessing.Queue()

 CONSUMER_KEYS = [{'queue':'product.order',
                   'routing_key':'product.order',
                   'internal_q':request_order_q}]
 #                 {'queue':'product.status',
 #                  'routing_key':'product.status',
 #                  'internal_q':request_status_q}]

 def main():
     # Launch consumers
     for key in CONSUMER_KEYS:
         cons = consumer.RabbitConsumer(rabbit_q=key['queue'],
                                        routing_key=key['routing_key'],
                                        internal_q=key['internal_q'])
         cons.start()

     # Check reques_order_q if not empty spaw a process and process message
     while True:
         time.sleep(0.5)
         if not request_order_q.empty():
             handler = worker.Worker(request_order_q.get())
             logger.info('Launching Worker')
             handler.start()

 if __name__ == "__main__":
     main()

And here is my Worker:

这是我的工人:

 import multiprocessing
 import sys 
 import time
 import base

 conf = base.get_settings()
 logger = base.logger(identity='worker')

 class Worker(multiprocessing.Process):

     def __init__(self, msg):
         super(Worker, self).__init__()
         self.msg = msg 
         self.daemon = True

     def run(self):
         logger.info('%s' % self.msg)
         time.sleep(10)
         sys.exit(1)

So after all the messages gets processed I can see processes with ps auxcommand. But I would really like them to be terminated once finished. Thanks.

因此,在处理完所有消息后,我可以使用ps aux命令查看进程。但我真的希望他们在完成后被终止。谢谢。

采纳答案by Markku K.

A couple of things:

几件事:

  1. Make sure the parent joinsits children, to avoid zombies. See Python Multiprocessing Kill Processes

  2. You can check whether a child is still running with the is_alive()member function. See http://docs.python.org/2/library/multiprocessing.html#multiprocessing.Process

  1. 确保父母joins是孩子,以避免僵尸。请参阅Python 多处理终止进程

  2. 您可以检查孩子是否仍在使用is_alive()成员函数运行。请参阅http://docs.python.org/2/library/multiprocessing.html#multiprocessing.Process

回答by Al Conrad

Use active_children. multiprocessing.active_children

使用 active_children。 multiprocessing.active_children

回答by Ioannis Filippidis

Using multiprocessing.active_childrenis better than Process.join. The function active_childrencleans any zombies created since the last call to active_children. The method joinawaits the selected process. During that time, other processes can terminate and become zombies, but the parent process will not notice, until the awaited method is joined. To see this in action:

使用multiprocessing.active_childrenProcess.join. 该函数active_children清除自上次调用以来创建的所有僵尸active_children。该方法join等待选定的进程。在此期间,其他进程可以终止并成为僵尸进程,但父进程不会注意到,直到加入等待的方法。要查看此操作:

import multiprocessing as mp
import time


def main():
    n = 3
    c = list()
    for i in xrange(n):
        d = dict(i=i)
        p = mp.Process(target=count, kwargs=d)
        p.start()
        c.append(p)
    for p in reversed(c):
        p.join()
        print('joined')


def count(i):
    print('{i} going to sleep'.format(i=i))
    time.sleep(i * 10)
    print('{i} woke up'.format(i=i))


if __name__ == '__main__':
    main()

The above will create 3 processes that terminate 10 second apart each. As the code is, the last process is joined first, so the other two, which terminated earlier, will be zombies for 20 seconds. You can see them with:

以上将创建 3 个进程,每个进程终止 10 秒。如代码所示,最后一个进程首先加入,因此其他两个提前终止的进程将在 20 秒内成为僵尸进程。您可以通过以下方式查看它们:

ps aux | grep Z

There will be no zombies if the processes are awaited in the sequence that they will terminate. Remove the reversedto see this case. However, in real applications we rarely know the sequence that children will terminate, so using joinwill result in some zombies.

如果进程按照它们将要终止的顺序等待,则不会有僵尸。删除reversed以查看此案例。但是,在实际应用中,我们很少知道子进程将终止的序列,因此使用join会导致一些僵尸。

The alternative active_childrendoes not leave any zombies. In the above example, replace the loop for p in reversed(c):with:

替代方案active_children不会留下任何僵尸。在上面的示例中,将循环替换为for p in reversed(c):

while True:
    time.sleep(1)
    if not mp.active_children():
        break

and see what happens.

看看会发生什么。