zombies zombie ver validar procesos proceso modo eliminar python linux multithreading

python - ver - ¿Cómo matar procesos zombies creados por multiprocesamiento del módulo?



validar procesos zombie (3)

Un par de cosas:

  1. Asegúrate de que el padre se joins sus hijos, para evitar zombies. Ver procesos de eliminación de multiprocesamiento de Python

  2. Puede verificar si un niño todavía se está ejecutando con la función miembro is_alive() . Consulte http://docs.python.org/2/library/multiprocessing.html#multiprocessing.Process

Soy muy nuevo en el módulo multiprocessing . Y solo traté de crear lo siguiente: Tengo un proceso que es un trabajo para obtener un mensaje de RabbitMQ y pasarlo a la cola interna ( multiprocessing.Queue ). Entonces, lo que quiero hacer es: generar un proceso cuando llega un nuevo mensaje. Funciona, pero una vez que finaliza el trabajo, deja un proceso zombie que no es terminado por su padre. Aquí está mi código:

Proceso principal:

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

Y aquí está mi Trabajador:

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)

Entonces, después de que todos los mensajes se procesan, puedo ver los procesos con el comando ps aux . Pero realmente me gustaría que terminen una vez que terminen. Gracias.


Usar multiprocessing.active_children es mejor que Process.join . La función active_children limpia todos los zombies creados desde la última llamada a active_children . El método de join espera el proceso seleccionado. Durante ese tiempo, otros procesos pueden terminar y convertirse en zombies, pero el proceso principal no se notará, hasta que se junte el método esperado. Para ver esto en acción:

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

Lo anterior creará 3 procesos que terminan en 10 segundos cada uno. Como es el código, el último proceso se une primero, por lo que los otros dos, que terminaron antes, serán zombies durante 20 segundos. Puedes verlos con:

ps aux | grep Z

No habrá zombies si los procesos se esperan en la secuencia que terminarán. Retire el reversed para ver este caso. Sin embargo, en aplicaciones reales rara vez conocemos la secuencia que los niños terminarán, por lo que el uso de la join dará como resultado algunos zombies.

La alternativa active_children no deja ningún zombies. En el ejemplo anterior, reemplace el bucle for p in reversed(c): con:

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

y mira lo que pasa.