Ce que vous observez est un bug dans cette version de bash.
kill -9 %1
ne tue pas le travail immédiatement. Vous pouvez observer cela avec ps
. Vous pouvez tracer le processus bash pour voir quand l' kill
appel système est appelé et tracer le sous-processus pour voir quand il reçoit et traite les signaux. Plus intéressant, vous pouvez aller voir ce qui se passe dans le processus.
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$
Dans un autre terminal:
% ps 3083
PID TTY STAT TIME COMMAND
3083 pts/4 Z 0:00 [sleep] <defunct>
Le sous-processus est un zombie . Il est mort: il ne lui reste qu'une entrée dans la table des processus (mais pas de mémoire, de code, de fichiers ouverts, etc.). L'entrée est conservée jusqu'à ce que son parent en prenne note et récupère son état de sortie en appelant l' wait
appel système ou l'un de ses frères et sœurs .
Un shell interactif est censé rechercher les enfants morts et les récolter avant d'imprimer une invite (sauf configuration contraire). Cette version de bash ne parvient pas à le faire dans certaines circonstances:
bash-4.3$ jobs -l
[1]+ 3083 Stopped sleep 9999
bash-4.3$ true
bash-4.3$ /bin/true
[1]+ Killed sleep 9999
Vous pouvez vous attendre à ce que bash signale «Tué» dès qu'il imprime l'invite après la kill
commande, mais ce n'est pas garanti, car il y a une condition de concurrence. Les signaux sont délivrés de manière asynchrone: l' kill
appel système revient dès que le noyau a déterminé le ou les processus auxquels délivrer le signal, sans attendre qu'il soit réellement délivré. Il est possible, et cela arrive dans la pratique, que bash ait le temps de vérifier l'état de son sous-processus, de constater qu'il n'est toujours pas mort ( wait4
ne signale aucun décès d'enfant) et d'imprimer que le processus est toujours arrêté. Ce qui ne va pas, c'est qu'avant l'invite suivante, le signal a été délivré ( ps
signale que le processus est mort), mais bash n'a toujours pas appeléwait4
(nous pouvons voir cela non seulement parce qu'il signale toujours le travail comme «Arrêté», mais parce que le zombie est toujours présent dans la table de processus). En fait, bash ne récolte le zombie que la prochaine fois qu'il doit appeler wait4
, lorsqu'il exécute une autre commande externe.
Le bug est intermittent et je n'ai pas pu le reproduire pendant que bash est tracé (probablement parce que c'est une condition de concurrence où bash doit réagir rapidement). Si le signal est délivré avant les vérifications bash, tout se passe comme prévu.