Lo que estás observando es un error en esta versión de bash.
kill -9 %1
mata el trabajo de inmediato. Puedes observar eso con ps
. Puede rastrear el proceso bash para ver cuándo kill
se llama a la llamada del sistema, y rastrear el subproceso para ver cuándo recibe y procesa las señales. Más interesante, puedes ir y ver qué está pasando con el proceso.
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$
En otra terminal:
% ps 3083
PID TTY STAT TIME COMMAND
3083 pts/4 Z 0:00 [sleep] <defunct>
El subproceso es un zombie . Está muerto: todo lo que queda es una entrada en la tabla de procesos (pero no hay memoria, código, archivos abiertos, etc.). La entrada se deja hasta que su padre tome nota y recupere su estado de salida llamando a la llamada del wait
sistema o a uno de sus hermanos .
Se supone que un shell interactivo verifica si hay niños muertos y los cosecha antes de imprimir un mensaje (a menos que esté configurado de otra manera). Esta versión de bash no puede hacerlo en algunas circunstancias:
bash-4.3$ jobs -l
[1]+ 3083 Stopped sleep 9999
bash-4.3$ true
bash-4.3$ /bin/true
[1]+ Killed sleep 9999
Puede esperar que bash informe "Muerto" tan pronto como se imprima el mensaje después del kill
comando, pero eso no está garantizado, porque hay una condición de carrera. Las señales se entregan de forma asíncrona: la kill
llamada del sistema vuelve tan pronto como el núcleo ha descubierto a qué proceso (s) entregar la señal, sin esperar a que se entregue realmente. Es posible, y sucede en la práctica, que bash tenga tiempo para verificar el estado de su subproceso, descubrir que aún no está muerto ( wait4
no informa la muerte de ningún niño) e imprimir que el proceso aún se detiene. Lo que está mal es que antes del próximo aviso, la señal se haya entregado ( ps
informa que el proceso está muerto), pero bash todavía no ha llamadowait4
(podemos ver eso no solo porque todavía informa que el trabajo está "Detenido", sino porque el zombi todavía está presente en la tabla de proceso). De hecho, bash solo cosecha al zombi la próxima vez que necesite llamar wait4
, cuando ejecuta algún otro comando externo.
El error es intermitente y no pude reproducirlo mientras se rastrea bash (presumiblemente porque es una condición de carrera en la que bash debe reaccionar rápidamente). Si la señal se entrega antes de las comprobaciones de bash, todo sucede como se esperaba.