Como posso matar um processo <defunct> cujo pai é init?

27

A transmissão está intermitentemente suspensa no meu NAS. Se eu enviar o SIGTERM, ele não desaparecerá da lista de processos e um <defunct>rótulo aparecerá próximo a ele. Se eu enviar um SIGKILL, ele ainda não desaparece e não consigo finalizar o pai porque ele está init. A única maneira de me livrar do processo e reiniciar o Transmission é reiniciar.

Percebo que a melhor coisa que posso fazer é tentar corrigir o Transmission (e tentei), mas sou iniciante na compilação e queria garantir que meus torrents terminassem antes de começar a mexer com ele.

Andy E
fonte
3
Ninguém está afirmando o óbvio ... um processo <defunct> de propriedade de "init" deve ser impossível! Esta é uma situação muito estranha! Você tem certeza?
JoelFan 12/04
@ JoelFan: Eu estava apenas olhando para ter certeza de que não estava esquecendo algo importante. Os zumbis que são filhos de initdevem desaparecer rapidamente, pois initespera periodicamente as crianças, pois uma de suas muitas tarefas comuns ... é <defunct>o mesmo que um zumbi?
D.Shawley
11
deixa pra lá ... <defunct>é exatamente o mesmo que um zumbi. initvai esperar seus filhos para que isso nunca aconteça em teoria. Gostaria de saber o que acontece se você enviar um SIGCHLDpara init?
precisa
@ JoelFan: sim, tenho certeza. O valor do PPID era 1 (init), por isso era impossível SIGKILL o processo.
Andy E
3
semelhante ao unix.stackexchange.com/a/5648
tshepang

Respostas:

35

Você não pode matar um <defunct>processo (também conhecido como processo de zumbi), pois ele já está morto. O sistema mantém processos zumbis para os pais coletarem o status de saída. Se o pai não coletar o status de saída, os processos zumbis permanecerão por toda a eternidade. A única maneira de se livrar desses processos zumbis é matando os pais. Se o pai for init, você poderá reiniciar apenas.

Os processos zumbis ocupam quase nenhum recurso; portanto, não há custo de desempenho para deixá-los permanecer. Embora ter processos zumbis por aí geralmente signifique que há um erro em alguns de seus programas. O Init geralmente deve coletar todas as crianças. Se o init tem filhos zumbis, existe um bug no init (ou em algum outro lugar, mas é um bug).

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

lesmana
fonte
9
initnunca pode ter filhos zumbis. Do artigo da wikipedia: Quando um processo perde seu pai, o init se torna seu novo pai. O Init executa periodicamente a chamada do sistema de espera para colher quaisquer zumbis com o init como pai. Uma das initresponsabilidades de colher órfãos e zumbis sem pais.
D.Shawley
14
@ D.Shawley: initpode ter erros embora. A substituição do init runitteve um erro que causa esse problema.
Camh
2
O init pode ter filhos extintos, talvez devido a um bug, mas pode. Porque eu estou olhando para um agora.
studgeek
Existe um programa que eu executei no terminal e entrei em um estado deficiente. Como explicado pelo @lesmana, quando fechei o terminal (pai), o programa saiu corretamente.
mk ..
6

Qualquer um que tentar consertar o código-fonte da Transmissão C deve ler sobre o truque "double fork" para evitar zumbis e manipuladores de sinais ... e como ele pode ser usado como parte de uma função de geração variável inteligente (consulte Desovar no 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
fonte
11
A bifurcação dupla impede processos zumbis forçando o kernel a definir seu pai como PID 1, que deve limpar os zumbis. Parece que Transmission já faz isso, já que seu pai já é um processo 1.
Jander
11
Existem vários problemas aqui. # 1: Somente os pais devem ligar exit(3); os filhos devem ligar em _exit(2)vez disso (caso contrário, você recebe vários fluxos de stdio, entre outros problemas). # 2: Isso execvp(3)poderia usar a perror(3)se falhar. # 3: Você deve usar em signal(SIGCHLD, SIG_IGN)vez de toda essa bagunça.
Kevin