Come posso uccidere un processo <defunct> il cui genitore è init?


27

La trasmissione è sospesa in modo intermittente sul mio NAS. Se invio SIGTERM, non scompare dall'elenco dei processi e <defunct>accanto appare un'etichetta. Se invio un SIGKILL, non scompare ancora e non riesco a interrompere il genitore perché è il genitore init. L'unico modo per sbarazzarmi del processo e riavviare la trasmissione è riavviare.

Mi rendo conto che la cosa migliore che posso fare è provare a correggere la trasmissione (e ci ho provato), ma sono un novizio nella compilazione e volevo assicurarmi che i miei torrent finissero prima di iniziare a rovinarlo.


3
Nessuno sta affermando l'ovvio ... un processo <defunct> di proprietà di "init" dovrebbe essere impossibile! Questa è una seduzione molto strana! Sei sicuro?
JoelFan,

@JoelFan: lo stavo solo cercando per assicurarmi di non dimenticare qualcosa di importante. Gli zombi di cui sono bambini initdovrebbero scomparire abbastanza rapidamente poiché initattendono periodicamente i bambini come uno dei suoi numerosi compiti comuni ... è <defunct>lo stesso di uno zombi?
D.Shawley,

1
non importa ... <defunct>è esattamente lo stesso di uno zombi. initaspetteranno i suoi figli, quindi ciò non dovrebbe mai accadere in teoria. Mi chiedo cosa succede se si invia un SIGCHLDa init?
D.Shawley,

@JoelFan: sì, ne sono sicuro. Il valore per PPID era 1 (init), quindi era impossibile SIGKILL il processo.
Andy E

Risposte:


35

Non puoi uccidere un <defunct>processo (noto anche come processo di zombi) in quanto è già morto. Il sistema mantiene i processi di zombi affinché il genitore raccolga lo stato di uscita. Se il genitore non raccoglie lo stato di uscita, i processi degli zombi rimarranno per sempre. L'unico modo per sbarazzarsi di quei processi di zombi è uccidere il genitore. Se il genitore è init, puoi solo riavviare.

I processi di zombi non richiedono quasi nessuna resa, quindi non ci sono costi di prestazione nel lasciarli indugiare. Anche se avere processi zombi in giro di solito significa che c'è un bug in alcuni dei tuoi programmi. Init dovrebbe di solito raccogliere tutti i bambini. Se init ha figli zombi, allora c'è un bug in init (o qualcos'altro, ma è un bug).

http://en.wikipedia.org/wiki/Zombie_process


9
initnon potrà mai avere figli di zombi. Dall'articolo di Wikipedia: quando un processo perde il suo genitore, init diventa il suo nuovo genitore. Init esegue periodicamente la chiamata di sistema di attesa per raccogliere eventuali zombi con init come genitore. Una delle initresponsabilità è quella di raccogliere orfani e zombi senza genitori.
D.Shawley,

14
@ D.Shawley: initpuò avere dei bug però. La sostituzione di init runitha avuto un bug che causa questo problema.
Camh,

2
init può avere figli defunti, forse a causa di un bug, ma può. Perché ne sto guardando uno proprio ora.
Studgeek

C'è questo programma che ho eseguito dal terminale ed è entrato in uno stato defunto. Come spiegato da @lesmana, quando ho chiuso il terminale (genitore) il programma è uscito in modo pulito.
mk ..

6

Chiunque cerchi di correggere il codice sorgente di Transmission C dovrebbe leggere il trucco del "double fork" per evitare zombi e gestori di segnali ... e come può essere usato come parte di una funzione di spawn variadica intelligente (vedi Spawning in Unix ).

excerpt from: 
   "Spawning in Unix", http://lubutu.com/code/spawning-in-unix

Double fork
This trick lets you spawn processes whilst avoiding zombies, without 
installing any signal handler. The first process forks and waits for its 
child; the second process forks and immediately exits and is reaped;
the third process is adopted by init, and executes the desired program. 
All zombies accounted for, since init is always waiting.

if(fork() == 0) {
   if(fork() == 0) {
       execvp(file, argv);
       exit(EXIT_FAILURE);
   }
   exit(EXIT_SUCCESS);
}
wait(NULL);

1
Il doppio fork impedisce i processi di zombi forzando il kernel a impostare il suo genitore su PID 1, che dovrebbe ripulire gli zombi. Sembra che la trasmissione lo faccia già, dato che il suo genitore è già processo 1.
Jander

1
Ci sono più problemi qui. # 1: solo il genitore dovrebbe chiamare exit(3); i bambini dovrebbero chiamare _exit(2)invece (altrimenti si ottengono più vampate di stdio, tra le altre questioni). # 2: che execvp(3)potrebbe usare a perror(3)se fallisce. # 3: dovresti semplicemente usare al signal(SIGCHLD, SIG_IGN)posto di tutto questo casino.
Kevin,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.