Comozumbisreais,umprocessodezumbisnãopodesermorto,porquejáestámorto.
Comoissoacontece
QuandonoLinux/Unixumprocessomorre/terminatodasasinformaçõesdoprocessosãoremovidasdamemóriadosistema,somenteodescritordeprocessopermanece.OprocessoentranoestadoZ(zumbi).Seuprocessopairecebeumsinaldokernel:SIGCHLD
,issosignificaqueumdeseusprocessosfilhossai,éinterrompidoourecomeçadepoisdeserinterrompido(nonossocaso,simplesmentesai).
Oprocessopaiagoraprecisaexecutarowait()
syscallparalerostatusdesaídaeoutrasinformaçõesdeseuprocessofilho.Entãoodescritoréremovidodamemóriaeoprocessonãoémaisumzumbi.
Seoprocessopainuncachamarowait()
syscall,odescritordoprocessozumbificaránamemóriaeconsumirácérebros.Normalmentevocênãovêprocessoszumbis,porqueoprocedimentoacimalevamenostempo.
Oamanhecerdosmortos
Cadadescritordeprocessoprecisadeumaquantidademuitopequenadememória,entãoalgunszumbisnãosãomuitoperigosos(comonavidareal).Umproblemaéquecadaprocessozumbimantémseuiddeprocesso,eumsistemaoperacionalLinux/Unixpossuiumnúmerolimitadodepid's.Seumsoftwareprogramadoindevidamentegerarmuitosprocessoszumbis,podeacontecerqueosprocessosnãopossammaisseriniciadosporquenãohámaisidentificaçõesdeprocessodisponíveis.
Então,seelesestãoemgruposenormes,elessãomuitoperigosos(comoemmuitosfilmesédemonstradomuitobem)
Comopodemosnosdefendercontraumahordadezumbis?
Umtironacabeçafuncionaria,maseunãoseiocomandoparaisso(oSIGKILLnãofuncionaporqueoprocessojáestámorto).
Bem,vocêpodeenviarSIGCHLDviakillparaoprocessopai,masquandoeleignoraessesinal,edepois?Suaúnicaopçãoémataroprocessopaiequeoprocessodeinicialização"adota" o zumbi. O Init chama periodicamente o wait()
syscall para limpar seus filhos zumbis.
No seu caso
No seu caso, você tem que enviar SIGCHLD para o processo de crond:
root@host:~# strace -p $(pgrep cron)
Process 1180 attached - interrupt to quit
Então, a partir 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ê que 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.