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

时间:2013-10-11 15:42:24

标签: python linux multithreading

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

主要流程:

 #!/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()

这是我的工人:

 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)

因此,在处理完所有消息之后,我可以看到具有ps aux命令的进程。但我真的希望他们一旦完成就被终止。 感谢。

3 个答案:

答案 0 :(得分:12)

有几件事:

  1. 确保父级joins为其子级,以避免僵尸。请参阅Python Multiprocessing Kill Processes

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

答案 1 :(得分:9)

Using <form id="loginform" action="./functions/dologin.php" method="post"> <input type="hidden" id="xc" name="xc" value="X"> <input type="hidden" id="yc" name="yc" value="X"> <button class="myButton" onclick="getLocation();">Login</button> </form> is better than multiprocessing.active_children. The function Process.join cleans any zombies created since the last call to active_children. The method active_children awaits 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:

join

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:

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()

There will be no zombies if the processes are awaited in the sequence that they will terminate. Remove the ps aux | grep Z to see this case. However, in real applications we rarely know the sequence that children will terminate, so using reversed will result in some zombies.

The alternative join does not leave any zombies. In the above example, replace the loop active_children with:

for p in reversed(c):

and see what happens.

答案 2 :(得分:1)

使用active_children。 multiprocessing.active_children