Por que um zumbi está esperando seu filho?

11

Estou pesquisando diferentes fontes, mas não consigo encontrar uma boa descrição da anatomia da criança que colhe. Este é um caso simples do que eu gostaria de entender.

$ cat <( sleep 100 & wait ) &
[1] 14247
$ ps ax -O pgid | grep $$
12126 12126 S pts/17   00:00:00 bash
14248 12126 S pts/17   00:00:00 bash
14249 12126 S pts/17   00:00:00 sleep 100
14251 14250 S pts/17   00:00:00 grep --color=auto 12126
$ kill -2 14248

$ ps ax -O pgid | grep $$
12126 12126 S pts/17   00:00:00 bash
14248 12126 Z pts/17   00:00:00 [bash] <defunct>
14249 12126 S pts/17   00:00:00 sleep 100
14255 14254 S pts/17   00:00:00 grep --color=auto 12126

Por que o zumbi está esperando a criança?

Você pode explicar este? Preciso conhecer C e ler o código-fonte do Bash para entender melhor isso ou existe alguma documentação? Eu já consultei:

Lançamento do GNU bash, versão 4.3.42 (1) (x86_64-pc-linux-gnu)

Linux 4.4.0-31-generic # 50-Ubuntu SMP Wed Jul 13 00:07:12 UTC 2016 x86_64 x86_64 x86_64 GNU / Linux


fonte
2
Observe que isso realmente não tem nada a ver com o bash (além do fato de que se você optar por usar o bash como seu shell, muitos processos serão iniciados por ele). Outros shells (tcsh, ksh, zsh, etc.) iniciam processos e executam essencialmente as mesmas funções do SO para lidar com eles.
Jamesqf
@jamesqf Interessante. Se você gostaria de expandir seu comentário para uma resposta completa, isso seria ótimo.
1
Exceto que não é realmente uma resposta, apenas assinale que você está procurando a resposta nos lugares errados :-) Qualquer bom livro sobre programação de sistemas * nix deve fornecer uma resposta muito melhor do que eu poderia escrever.
Jamesqf

Respostas:

17

O zumbi não está esperando por seu filho. Como qualquer processo zumbi, ele permanece por aí até que seus pais o colecionem.

Você deve exibir todos os processos envolvidos para entender o que está acontecendo e examinar o PPID também. Use esta linha de comando:

ps -t $(tty) -O ppid,pgid

O pai do processo que você está matando é cat. O que acontece é que o bash executa o comando background cat <( sleep 100 & wait )em um subshell. Como a única coisa que esse subshell faz é configurar algum redirecionamento e executar um comando externo, esse subshell é substituído pelo comando externo. Aqui está o resumo:

  • O bash original (12126) chama forkpara executar o comando cat <( sleep 100 & wait )em segundo plano em um filho (14247).
    • O filho (14247) chama pipepara criar um canal e, em seguida, forkpara criar um filho para executar a substituição do processo sleep 100 & wait.
      • O neto (14248) chama forkpara ser executado sleep 100em segundo plano. Como o neto não é interativo, o processo em segundo plano não é executado em um grupo de processos separado. Então o neto espera sleepsair.
    • O filho (14247) chama setpgid(é um trabalho em segundo plano em um shell interativo para obter seu próprio grupo de processos) e depois execveexecuta cat. (Estou um pouco surpreso que a substituição do processo não esteja ocorrendo no grupo de processos em segundo plano.)
  • Você mata o neto (14248). Seu pai está em execução cat, que não sabe nada sobre nenhum processo filho e não tem ligações comerciais wait. Como o pai do neto não o colhe, o neto fica para trás como um zumbi.
  • Eventualmente, catsai - ou porque você o mata, ou porque sleepretorna e fecha o canal para catver o final de sua entrada. Nesse ponto, o pai do zumbi morre, então o zumbi é coletado pelo init e o colhe.

Se você alterar o comando para

{ cat <( sleep 100 & wait ); echo done; } &

depois caté executado em um processo separado, não no filho do processo original do bash: o primeiro filho precisa ficar para trás para executar echo done. Nesse caso, se você matar o neto, ele não permanecerá como um zumbi, porque a criança (que ainda está executando o bash naquele momento) a colhe.

Veja também Como o linux lida com o processo zumbi e Pode um zumbi ter órfãos? As crianças órfãs serão perturbadas ao colher o zumbi?

Gilles 'SO- parar de ser mau'
fonte
Fiquei surpreso com a coisa do grupo de processos também. Parece que foi um bug e agora está corrigido no ramo mestre do bash.
PSKocik
"A festança original espera por seu filho (14247)." Por que ou de que maneira? A criança deve executar em segundo plano e não há chamada explícita. Qual é a diferença entre o bash original (14246) aguardando 14247 e 14247 (que está sendo executado cat) e não aguardando 14248 (aguardando sleep)? Existe alguma memória de quem espera por quem, que a criança (14247) perdeu e a festança original (14246) não, ou talvez uma lista de sinais como o SIGCHLD de quem deveria ser chamado e o 14247 (agora em execução bash) cancelado a assinatura com em relação a 14248?
1
@tomas, quis dizer que o bash original chama waitseu filho, ou seja, ele o colhe. Percebo como isso seria confuso, removi a frase que não estava no ponto certo cronologicamente falando. As informações de que um processo morreu vão para o pai do processo, um processo não pode "se inscrever" para receber informações sobre a morte de outro processo.
Gilles 'SO- stop be evil'
6

Zumbi não está esperando a criança. Em vez disso, o zumbi é o processo que já morreu (por conta própria ou foi morto - como no seu exemplo), teve seu código, dados e pilha desalocados e agora contém apenas seu código de saída, aguardando o pai chamar wait(2)para recuperá-lo. (e, portanto, finalmente limpe completamente a entrada do processo da tabela de processos)

No seu exemplo, quando o sono termina (ou é interrompido), o pai lê os status de saída e colhe os zumbis. Veja acima mencionado wait(2)para detalhes.

Matija Nalis
fonte