Proceso zombie en daemon multiproceso python

Después de investigar los demonios de Python, este recorrido parecía ser el más robusto: http://www.jejik.com/articles/2007/02/a_simple_unix_linux_daemon_in_python/

Ahora estoy tratando de implementar un grupo de trabajadores dentro de la clase daemon que creo que está funcionando (no he probado el código a fondo), excepto que en el cierre obtengo un proceso zombie. He leído que debo esperar el código de retorno del niño, pero no puedo ver exactamente cómo debo hacer esto todavía.

Aquí hay algunos fragmentos de código:

def stop(self): ... try: while 1: self.pool.close() self.pool.join() os.kill(pid, SIGTERM) time.sleep(0.1) ... 

Aquí he probado os.killpg y varios métodos de os.wait pero sin ninguna mejora. También he jugado closing / joining la piscina antes y después del os.kill . Este bucle tal como está, nunca termina y tan pronto como llega al os.kill obtengo un proceso zombie. self.pool = Pool(processes=4) ocurre en la sección __init__ del daemon. Desde la run(self) que se ejecuta después del start(self) , llamaré self.pool.apply_async(self.runCmd, [cmd, 10], callback=self.logOutput) . Sin embargo, quería abordar este proceso zombie antes de analizarlo.

¿Cómo puedo implementar correctamente el grupo dentro del demonio para evitar este proceso zombie?

No es posible tener un 100% de confianza en una respuesta sin saber qué está pasando en el proceso del niño / demonio, pero considere si esto podría ser así. Ya que tiene subprocesos de trabajo en su proceso hijo, en realidad necesita construir algo de lógica para unir todos esos subprocesos una vez que reciba el SIGTERM. De lo contrario, es posible que el proceso no finalice (e incluso si lo hace, es posible que no se cierre correctamente). Para hacer esto necesitas:

  • escriba un manejador de señales para usar en el proceso hijo / demonio que captura la señal SIGTERM y activa un evento para su hilo principal
  • instale el manejador de señales en el hilo principal (muy importante) del proceso hijo / demonio
  • el controlador de eventos para SIGTERM debe emitir instrucciones de detención a TODOS los hilos en el proceso hijo / demonio
  • todos los subprocesos deben estar unidos () ed cuando estén listos (si asumiera que SIGTERM destruiría automáticamente todo lo que pueda tener para implementar esta lógica también)
  • Una vez que todo esté unido y limpiado, puedes salir del hilo principal.

Si tiene hilos para E / S y todo tipo de cosas, entonces esto será una tarea real.

Además, a través del experimento, he descubierto que la estrategia particular para su oyente de eventos es importante cuando está utilizando controladores de señales. Por ejemplo, si usa select.select () debe usar un tiempo de espera y reintentar si se produce el tiempo de espera; De lo contrario, su controlador de señal no se ejecutará. Si tiene un objeto Queue.Queue para eventos, y su detector de eventos llama a su método .get (), debe usar un tiempo de espera, de lo contrario su controlador de señales no se ejecutará. (El controlador de señales “real” implementado en C dentro de la VM se ejecuta, pero su controlador de señales Python no lo hace a menos que use los tiempos de espera).

¡Buena suerte!