O que você está observando é um bug nesta versão do bash.
kill -9 %1
mata o trabalho imediatamente. Você pode observar isso com ps
. Você pode rastrear o processo bash para ver quando a kill
chamada do sistema é chamada e rastrear o subprocesso para ver quando recebe e processa os sinais. Mais interessante, você pode ver o que está acontecendo com o processo.
bash-4.3$ sleep 9999
^Z
[1]+ Stopped sleep 9999
bash-4.3$ kill -9 %1
[1]+ Stopped sleep 9999
bash-4.3$ jobs
[1]+ Stopped sleep 9999
bash-4.3$ jobs -l
[1]+ 3083 Stopped sleep 9999
bash-4.3$
Em outro terminal:
% ps 3083
PID TTY STAT TIME COMMAND
3083 pts/4 Z 0:00 [sleep] <defunct>
O subprocesso é um zumbi . Está morto: tudo o que resta é uma entrada na tabela de processos (mas não há memória, código, arquivos abertos etc.). A entrada é deixada em aberto até que seu pai ou mãe notifique e recupere seu status de saída chamando a wait
chamada de sistema ou um de seus irmãos .
Um shell interativo deve verificar se há filhos mortos e colhê-los antes de imprimir um prompt (a menos que configurado de outra forma). Esta versão do bash falha ao fazê-lo em algumas circunstâncias:
bash-4.3$ jobs -l
[1]+ 3083 Stopped sleep 9999
bash-4.3$ true
bash-4.3$ /bin/true
[1]+ Killed sleep 9999
Você pode esperar que o bash relate "Killed" assim que imprimir o prompt após o kill
comando, mas isso não é garantido, porque há uma condição de corrida. Os sinais são entregues de forma assíncrona: a kill
chamada do sistema retorna assim que o kernel descobre para quais processos entregar o sinal, sem esperar que ele seja realmente entregue. É possível, e acontece na prática, que o bash tenha tempo para verificar o status de seu subprocesso, descobrir que ele ainda não está morto ( wait4
não relata nenhuma morte infantil) e imprimir que o processo ainda está parado. O que há de errado é que, antes do próximo prompt, o sinal foi entregue ( ps
relata que o processo está morto), mas o bash ainda não foi chamadowait4
(podemos ver isso não apenas porque ele ainda relata o trabalho como "Parado", mas porque o zumbi ainda está presente na tabela de processos). De fato, o bash só colhe o zumbi na próxima vez que ele precisar chamar wait4
, quando executa algum outro comando externo.
O bug é intermitente e eu não pude reproduzi-lo enquanto o bash é rastreado (presumivelmente porque é uma condição de corrida em que o bash precisa reagir rapidamente). Se o sinal é entregue antes das verificações do bash, tudo acontece como esperado.