Quello che stai osservando è un bug in questa versione di bash.
kill -9 %1
uccide immediatamente il lavoro. Puoi osservarlo con ps
. È possibile tracciare il processo bash per vedere quando kill
viene chiamata la chiamata di sistema e tracciare il sottoprocesso per vedere quando riceve ed elabora i segnali. Ancora più interessante, puoi andare a vedere cosa sta succedendo al 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$
In un altro terminale:
% ps 3083
PID TTY STAT TIME COMMAND
3083 pts/4 Z 0:00 [sleep] <defunct>
Il sottoprocesso è uno zombi . È morto: tutto ciò che rimane è una voce nella tabella dei processi (ma nessuna memoria, codice, file aperti, ecc.). La voce viene lasciata in giro fino a quando il suo genitore non prende atto e recupera il suo stato di uscita chiamando la wait
chiamata di sistema o uno dei suoi fratelli .
Una shell interattiva dovrebbe verificare la presenza di bambini morti e raccoglierli prima di stampare un prompt (se non configurato diversamente). Questa versione di bash non riesce a farlo in alcune circostanze:
bash-4.3$ jobs -l
[1]+ 3083 Stopped sleep 9999
bash-4.3$ true
bash-4.3$ /bin/true
[1]+ Killed sleep 9999
Potresti aspettarti che bash riporti "Ucciso" non appena stampa il prompt dopo il kill
comando, ma ciò non è garantito, perché c'è una condizione di competizione. I segnali vengono consegnati in modo asincrono: la kill
chiamata di sistema ritorna non appena il kernel ha capito a quali processi inviare il segnale, senza aspettare che venga effettivamente consegnato. È possibile, e in pratica accade, che bash abbia il tempo di controllare lo stato del suo sottoprocesso, scoprire che non è ancora morto ( wait4
non segnala la morte di alcun bambino) e stampare che il processo è ancora interrotto. Ciò che è sbagliato è che prima del prossimo prompt, il segnale è stato consegnato ( ps
segnala che il processo è morto), ma bash non ha ancora chiamatowait4
(possiamo vederlo non solo perché riporta ancora il lavoro come "Interrotto", ma perché lo zombi è ancora presente nella tabella dei processi). In effetti, bash raccoglie lo zombi solo la prossima volta che deve chiamare wait4
, quando viene eseguito un altro comando esterno.
Il bug è intermittente e non sono riuscito a riprodurlo mentre viene tracciato bash (presumibilmente perché è una condizione di gara in cui bash deve reagire rapidamente). Se il segnale viene inviato prima dei controlli bash, tutto accade come previsto.