2013-04-08 22 views
11

Ho un processo di multiprocessing Python 2.7 che non verrà chiuso all'uscita del processo padre. Ho impostato la flag daemon che dovrebbe costringerlo ad uscire sulla morte dei genitori. I documenti dicono che:Daemon multiprocesso non terminato sull'uscita principale

"Quando un processo termina, tenta di terminare tutti i suoi processi figlio demoniaci".

p = Process(target=_serverLaunchHelper, args=args) 
p.daemon = True 
print p.daemon # prints True 
p.start() 

Quando ho terminare il processo padre tramite un comando kill il daemon è rimasto vivo e funzionante (che blocca la porta su corsa successiva). Il processo figlio sta avviando un SimpleHttpServer e chiama serve_forever senza fare altro. La mia ipotesi è che la parte "tentativi" dei documenti significhi che il processo di blocco del server stia bloccando la morte del processo e che di conseguenza il processo venga reso orfano. Potrei fare in modo che il bambino spinga il serving in un altro Thread e abbia il controllo del thread principale per l'id del processo padre, ma questo sembra un sacco di codice per replicare semplicemente la funzionalità del demone.

Qualcuno ha idea del motivo per cui il flag del daemon non funziona come descritto? Questo è ripetibile su windows8 64 bit e ubuntu12 32 bit vm.

Un riduceva versione della funzione processo è inferiore:

def _serverLaunchHelper(port) 
    httpd = SocketServer.TCPServer(("", port), Handler) 
    httpd.serve_forever() 

risposta

9

Quando un processo termina, si tenta di risolvere tutti i suoi processi figli demoniaci.

La parola chiave qui è "tentativi". Inoltre, "esce".

A seconda della piattaforma e dell'implementazione, è possibile che l'unico modo per arrestare i processi figlio demoniaci sia farlo in modo esplicito. Se il processo genitore esce normalmente, ha la possibilità di farlo in modo esplicito, quindi tutto va bene. Ma se il processo genitore è terminato bruscamente, non è così.

Per CPython in particolare, se si guarda al the source, terminando i processi demoniaci viene gestita allo stesso modo di unire processi non demoniaci: camminando active_children() in una funzione atexit. Quindi, i tuoi demoni saranno uccisi se e solo se i tuoi gestori di atexit potranno correre. E, come documenti di quel modulo dire:

Nota: le funzioni registrate tramite questo modulo non vengono chiamati quando il programma viene ucciso da un segnale non gestita da Python, quando viene rilevato un errore fatale in Python, o quando os._exit() è chiamato.

A seconda di come stai uccidendo il genitore, potresti essere in grado di aggirare questo problema aggiungendo un gestore di segnali per intercettare la terminazione brusca. Ma potresti non farlo, ad esempio, su POSIX, SIGKILL non è intercettabile, quindi se si è kill -9 $PARENTPID, questa non è un'opzione.

Un'altra opzione è quella di uccidere il gruppo di processi, anziché solo il processo padre. Ad esempio, se il tuo genitore ha PID 12345, kill -- -12345 su Linux lo ucciderà e tutti i suoi figli (supponendo che tu non abbia fatto niente di speciale).

+3

Va bene, quindi se voglio davvero garantire che i bambini smettano quando il genitore muore, ho bisogno di programmare la logica nei processi figli per vedere scomparire i loro genitori. Grazie per la risposta chiara e veloce! – Pyrce

Problemi correlati