Entendendo e Lidando com Processos Zumbi no Linux

Entendendo e Lidando com Processos Zumbi no Linux

O que é um processo zumbi?

Um processo zumbi é um processo filho que terminou a execução mas ainda tem uma entrada na tabela de processos (código de estado Z, também exibido como [defunct]). O processo em si não está mais executando -- não consome CPU nem memória -- mas seu status de saída ainda não foi coletado pelo processo pai.

$ ps aux | grep Z
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
www-data  1234  0.0  0.0      0     0 ?        Z    10:01   0:00 [defunct]

O Z na coluna STAT identifica um zumbi.

Por que processos zumbi ocorrem?

A causa raiz é um processo pai que nunca chama wait() ou waitpid() para coletar o status de saída do filho.

Quando um processo termina, o kernel armazena seu status de saída na tabela de processos e envia SIGCHLD ao pai. A entrada permanece lá até o pai recuperar o status. Se o pai nunca o faz, o filho se torna um zumbi permanente.

Causas comuns:

  • O pai ignora SIGCHLD sem configurar coleta automática
  • O pai tem um bug no seu handler de sinal
  • O pai está travado e não consegue processar sinais

Você não pode matar um zumbi com kill -9 -- o processo já está morto. Apenas o pai (ou seu desaparecimento) pode fazer um zumbi desaparecer.

Como detectar zumbis

Encontrar zumbis e seu pai

$ ps -el | grep Z
F S   UID   PID  PPID  C PRI  NI ADDR SZ WCHAN  TTY          TIME CMD
4 Z  1000  1234  1100  0  80   0 -     0 -      pts/0    00:00:00 process

A coluna PPID mostra o PID do pai (1100 neste exemplo). Confirme o pai com:

$ ps aux | awk 'NR==1 || $2==1100'

Monitorar contagem de zumbis com top

$ top
Tasks: 142 total,   1 running, 141 sleeping,   0 stopped,   2 zombie

Uma contagem de zumbis crescendo constantemente indica um bug continuo em um processo pai.

Como corrigir processos zumbi

Opção 1: sinalizar o pai com SIGCHLD

Se o pai pode lidar com SIGCHLD, enviar o sinal pode fazê-lo chamar wait() e coletar o zumbi.

$ kill -SIGCHLD <PPID>

Opção 2: encerrar o processo pai

Quando o pai termina, o novo pai do zumbi se torna init (PID 1) ou systemd, que o coleta imediatamente.

$ kill <PPID>

Se o pai não responde:

$ kill -9 <PPID>

Antes de forçar o encerramento de um pai que é um serviço (nginx, mysqld, etc.), avalie o impacto nas conexões dependentes e na integridade dos dados.

Opção 3: reiniciar o sistema

Um último recurso quando zumbis se acumularam a um nível que prejudica a operação normal. Um reboot reinicializa a tabela de processos.

Processos zumbi são perigosos?

Alguns poucos zumbis não causam dano real. Eles não consomem CPU nem memória.

Porém, eles se tornam um problema em escala:

  • Esgotamento de PID: O teto padrão de PID do Linux (/proc/sys/kernel/pid_max) é 32.768. Se zumbis se acumulam, os PIDs disponíveis se esgotam e novos processos não podem iniciar.
  • Pressão na tabela de processos: Cada entrada consome uma pequena quantidade de memória do kernel.

Verifique seu limite de PID atual:

$ cat /proc/sys/kernel/pid_max
32768

Prevenindo processos zumbi no código da aplicação

Zumbis são um sintoma de um bug na aplicação pai. A correção real pertence ao código.

  • Chame waitpid(-1, NULL, WNOHANG) em um loop dentro de um handler SIGCHLD
  • Use a técnica de double fork para orfanar o neto sob init
  • Defina SIGCHLD como SIG_IGN -- sistemas compatíveis com POSIX fazem a coleta automática dos filhos

Próximas leituras