
Me esfuerzo mucho por entender qué estoy haciendo mal y por qué.
Tengo un launch.sh
script que se inicia process.sh
.
lanzamiento.sh
#!/bin/bash
while true; do
./process.sh
done
proceso.sh
#!/bin/bash
function signalHandler() {
for i in {1..2}; do
sleep 0.1s
echo "process.sh: cleanup $i"
done
exit 130
}
trap "signalHandler" "SIGINT"
while true; do
sleep 1s
done
cuando corro
./launch.sh &
y luego matarlo con
kill -s SIGINT -$!
donde $!
obtiene el PID del último comando (launch.sh) y el menos envía la señal a todos los niños, luego launch.sh
continúa. ¿Por qué?
Esperaba el siguiente comportamiento (según este blogSeñal y golpe) :
el shell A con el script launch.sh
ejecutándose en segundo plano se interrumpe, Bash espera hasta que process.sh
finaliza. Dado que process.sh
regresa de forma anormal (salida 130) debido al controlador de señal en process.sh
, el shell A debería salir. ¿Por qué no es así?
Si el estado de este niño indica que salió de manera anormal debido a esa señal, el shell limpia, elimina su controlador de señal y se elimina nuevamente para activar la acción predeterminada del sistema operativo (salida anormal). Alternativamente, ejecuta el controlador de señales del script tal como está configurado con trap y continúa.
Respuesta1
En primer lugar, exit 130
no es una salida anormal. Es una salida normal, con estado de salida 130. Como se puede ver enman 3 wait
(POSIX):
If the information pointed to by stat_loc was stored by a call to
waitpid() that specified the WUNTRACED and WCONTINUED flags,
exactly one of the macros WIFEXITED(*stat_loc), WIFSIGNALED(*stat_loc),
WIFSTOPPED(*stat_loc), and WIFCONTINUED(*stat_loc) shall evaluate to
a non-zero value.
WIFEXITED
comprueba la salida normal y WIFSIGNALLED
se termina debido a una señal no captada. Dado que estos son mutuamente excluyentes, exit 130
es normal.
Que el estado de salida sea 130 cuando un proceso muere por SIGINT se debe a que bash lo establece en 130 fuera del proceso porque detectó una salida debido a SIGINT:¿Por qué bash establece $? (estado de salida) a distinto de cero en Ctrl-C o Ctrl-Z?
En segundo lugar, un proceso que maneja SIGINT y luego muere debería suprimirse con SIGINT. La wiki de Greg (un excelente recurso para temas de shell) tieneuna nota sobre esto:
Si elige configurar un controlador para SIGINT (en lugar de usar la trampa EXIT), debe tener en cuenta que un proceso que sale en respuesta a SIGINT deberíasuicidarse con SIGNOen lugar de simplemente salir, para evitar causar problemas a la persona que llama. De este modo:
trap 'rm -f "$tempfile"; trap - INT; kill -INT $$' INT
Ahora, si cambiaste a exit 130
:
trap - INT
kill -INT $$
Verías el comportamiento esperado.