Comment puis-je tuer un processus <defunct> dont le parent est init?

27

La transmission est suspendue par intermittence sur mon NAS. Si j'envoie SIGTERM, il ne disparaît pas de la liste des processus et une <defunct>étiquette apparaît à côté. Si j'envoie un SIGKILL, il ne disparaît toujours pas et je ne peux pas terminer le parent parce que le parent l'est init. La seule façon de me débarrasser du processus et de redémarrer la transmission est de redémarrer.

Je me rends compte que la meilleure chose que je puisse faire est d'essayer de réparer Transmission (et j'ai essayé), mais je suis un novice dans la compilation et je voulais m'assurer que mes torrents se terminaient avant de commencer à jouer avec.

Andy E
la source
3
Personne ne dit l'évidence ... un processus <defunct> appartenant à "init" devrait être impossible! C'est une situation très étrange! Êtes-vous sûr?
JoelFan
@JoelFan: Je cherchais juste cela pour m'assurer que je n'oubliais pas quelque chose d'important. Les zombies qui sont des enfants initdevraient disparaître assez rapidement car initattend périodiquement les enfants comme l'une de ses nombreuses tâches courantes ... est <defunct>la même chose qu'un zombie?
D.Shawley
1
nevermind ... <defunct>est exactement la même chose qu'un zombie. initattendra ses enfants donc cela ne devrait jamais arriver en théorie. Je me demande ce qui se passe si vous envoyez un SIGCHLDà init?
D.Shawley
@JoelFan: oui, j'en suis sûr. La valeur de PPID était 1 (init), il était donc impossible de SIGKILL le processus.
Andy E
3
similaire à unix.stackexchange.com/a/5648
tshepang

Réponses:

35

Vous ne pouvez pas tuer un <defunct>processus (également appelé processus zombie) car il est déjà mort. Le système conserve les processus zombies pour que le parent collecte l'état de sortie. Si le parent ne collecte pas le statut de sortie, les processus zombies resteront pour toujours. La seule façon de se débarrasser de ces processus zombies est de tuer le parent. Si le parent est init, vous ne pouvez que redémarrer.

Les processus zombies ne prennent presque pas de ressources, il n'y a donc aucun coût de performance à les laisser s'attarder. Bien qu'avoir des processus zombies signifie généralement qu'il y a un bug dans certains de vos programmes. Init devrait généralement recueillir tous les enfants. Si init a des enfants zombies, il y a un bogue dans init (ou quelque chose d'autre mais c'est un bogue).

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

lesmana
la source
9
initne peut jamais avoir d'enfants zombies. De l'article de wikipedia: Lorsqu'un processus perd son parent, init devient son nouveau parent. Init exécute périodiquement l'appel système wait pour récolter tous les zombies avec init comme parent. L'une de initses responsabilités est de récolter des orphelins et des zombies sans parents.
D.Shawley
14
@ D.Shawley: initpeut cependant avoir des bugs. Le remplacement init runita eu un bogue qui provoque ce problème.
camh
2
init peut avoir des enfants disparus, peut-être à cause d'un bug, mais c'est possible. Parce que j'en regarde un en ce moment.
studgeek
Il y a ce programme que j'ai exécuté depuis le terminal et qui est entré dans un état défunt. Comme expliqué par @lesmana, lorsque j'ai fermé le terminal (parent), le programme est sorti proprement.
mk ..
6

Quiconque essaie de corriger le code source de Transmission C devrait lire l'astuce "double fork" pour éviter les zombies et les gestionnaires de signaux ... et comment il peut être utilisé dans le cadre d'une fonction d'apparition variadique intelligente (voir Spawning sous 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);
nazar
la source
1
La double fourche empêche les processus zombies en forçant le noyau à définir son parent sur PID 1, qui est censé nettoyer les zombies. On dirait que Transmission le fait déjà, puisque son parent est déjà le processus 1.
Jander
1
Il y a plusieurs problèmes ici. # 1: Seul le parent doit appeler exit(3); les enfants doivent appeler à la _exit(2)place (sinon vous obtenez plusieurs vidages stdio, entre autres). # 2: Cela execvp(3)pourrait utiliser un en perror(3)cas d'échec. # 3: Vous devez simplement utiliser à la signal(SIGCHLD, SIG_IGN)place de tout ce gâchis.
Kevin