¿Por qué el progtwig daemon no sale sin join ()?

La respuesta podría estar justo frente a mí en el enlace de abajo, pero todavía no entiendo. Estoy seguro de que después de que alguien me explique esto, Darwin me llamará.

El ejemplo está en este enlace aquí , aunque he hecho algunos cambios para intentar experimentar y ayudarme a comprender.

Aquí está el código:

import multiprocessing import time import sys def daemon(): p = multiprocessing.current_process() print 'Starting: ', p.name, p.pid sys.stdout.flush() time.sleep(2) print 'Exiting: ', p.name, p.pid sys.stdout.flush() def non_daemon(): p = multiprocessing.current_process() print 'Starting: ', p.name, p.pid sys.stdout.flush() time.sleep(6) print 'Exiting: ', p.name, p.pid sys.stdout.flush() if __name__ == '__main__': d = multiprocessing.Process(name='daemon', target=daemon) d.daemon = True n = multiprocessing.Process(name='non-daemon', target=non_daemon) n.daemon = False d.start() time.sleep(1) n.start() # d.join() 

Y la salida del código es:

 Starting: daemon 6173 Starting: non-daemon 6174 Exiting: non-daemon 6174 

Si la combinación () al final no tiene comentarios, la salida es:

 Starting: daemon 6247 Starting: non-daemon 6248 Exiting: daemon 6247 Exiting: non-daemon 6248 

Estoy confundido porque el sueño del demonio es de 2 segundos, mientras que el no demonio es de 6 segundos. ¿Por qué no imprime el mensaje “Saliendo” en el primer caso? El daemon debería haberse despertado antes que el no daemon e imprimió el mensaje.

La explicación del sitio es como tal:

La salida no incluye el mensaje “Saliendo” del proceso del daemon, ya que todos los procesos que no son del daemon (incluido el progtwig principal) salen antes de que el proceso del daemon se active después de su suspensión de 2 segundos.

pero lo cambié de tal manera que el daemon debería haberse despertado antes que el no daemon. ¿Que me estoy perdiendo aqui? Gracias de antemano por tu ayuda.

EDITAR: Olvidé mencionar que estoy usando python 2.7 pero aparentemente este problema también está en python 3.x

Esta fue una diversión para rastrear. Los documentos son un tanto engañosos, ya que describen los procesos no daemon como si fueran todos equivalentes; la existencia de cualquier proceso no daemon significa que el proceso “familia” está vivo. Pero no es así como se implementa. El proceso padre es “más igual” que otros; multiprocessing registra un controlador atexit que hace lo siguiente:

 for p in active_children(): if p.daemon: info('calling terminate() for daemon %s', p.name) p._popen.terminate() for p in active_children(): info('calling join() for process %s', p.name) p.join() 

Entonces, cuando el proceso principal finaliza, primero terminate s todos los procesos secundarios del daemon , luego se join a todos los procesos secundarios para esperar en los secundarios que no son daemon y limpiar los recursos de los secundarios del daemon .

Debido a que realiza la limpieza en este orden, un momento después de que start Process no daemon , el proceso principal comienza la limpieza y terminate fuerza el Process daemon .

Tenga en cuenta que solucionar este problema puede ser tan simple como join al proceso no daemon manualmente, no solo join al proceso daemon (que anula completamente el punto entero de un daemon ); eso evita que se atexit controlador atexit , retrasando la limpieza que terminate el daemon child.

Podría decirse que es un error (uno que parece existir hasta 3.5.1; me lo reproché a mí mismo), pero es discutible si se trata de un error de comportamiento o de un error de documentación.