Como os zumbis reais, um processo de zumbis não pode ser morto, porque já está morto.
Como isso acontece
Quando no Linux / Unix um processo morre / termina todas as informações do processo são removidas da memória do sistema, apenas o descritor do processo permanece. O processo entra no estado Z (zumbi). Seu processo pai recebe um sinal do kernel:, SIGCHLD
isso significa que um dos processos filhos sai, é interrompido ou continua após ser interrompido (no nosso caso, simplesmente sai).
O processo pai agora precisa executar o wait()
syscall para ler o status de saída e outras informações do processo filho. Em seguida, o descritor é removido da memória e o processo não é mais um zumbi.
Se o processo pai nunca chamar o wait()
syscall, o descritor de processo zumbi permanece na memória e come cérebros. Normalmente você não vê processos zumbis, porque o procedimento acima leva menos tempo.
O amanhecer dos mortos
Cada descritor de processo precisa de uma quantidade muito pequena de memória; portanto, alguns zumbis não são muito perigosos (como na vida real). Um problema é que cada processo zumbi mantém sua identificação de processo e um sistema operacional Linux / Unix possui um número limitado de pid's. Se um software programado incorretamente gerar muitos processos zumbis, pode acontecer que os processos não possam mais ser iniciados porque não há mais IDs de processo disponíveis.
Então, se eles estão em grandes grupos, eles são muito perigosos (como em muitos filmes é demonstrado muito bem)
Como podemos nos defender contra uma horda de zumbis?
Um tiro na cabeça funcionaria, mas não sei o comando para isso (SIGKILL não funcionará porque o processo já está morto).
Bem, você pode enviar SIGCHLD via kill para o processo pai, mas quando ele ignora esse sinal, o que acontece então? Sua única opção é matar o processo pai e que o processo init "adote" o zumbi. Init chama periodicamente o administrador wait()
para limpar seus filhos zumbis.
No seu caso
No seu caso, você deve enviar o SIGCHLD para o processo crond:
root@host:~# strace -p $(pgrep cron)
Process 1180 attached - interrupt to quit
Em seguida, de outro terminal:
root@host:~$ kill -17 $(pgrep cron)
A saída é:
restart_syscall(<... resuming interrupted call ...>) = ? ERESTART_RESTARTBLOCK (To be restarted)
--- SIGCHLD (Child exited) @ 0 (0) ---
wait4(-1, 0x7fff51be39dc, WNOHANG, NULL) = -1 ECHILD (No child processes) <-- Here it happens
rt_sigreturn(0xffffffffffffffff) = -1 EINTR (Interrupted system call)
stat("/etc/localtime", {st_mode=S_IFREG|0644, st_size=1892, ...}) = 0
rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
rt_sigaction(SIGCHLD, NULL, {0x403170, [CHLD], SA_RESTORER|SA_RESTART, 0x7fd6a7e9d4a0}, 8) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
nanosleep({42, 0}, ^C <unfinished ...>
Process 1180 detached
Você vê o wait4()
syscall retorna -1 ECHILD, o que significa que nenhum processo filho está lá. Portanto, a conclusão é: o cron reage ao syscall do SIGCHLD e não deve forçar o apocalipse.