bash no sale ante una salida anormal del proceso hijo debido a una señal

bash no sale ante una salida anormal del proceso hijo debido a una señal

Me esfuerzo mucho por entender qué estoy haciendo mal y por qué.

Tengo un launch.shscript 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.shcontinúa. ¿Por qué?


Esperaba el siguiente comportamiento (según este blogSeñal y golpe) :

el shell A con el script launch.shejecutándose en segundo plano se interrumpe, Bash espera hasta que process.shfinaliza. Dado que process.shregresa 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 130no 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.

WIFEXITEDcomprueba la salida normal y WIFSIGNALLEDse termina debido a una señal no captada. Dado que estos son mutuamente excluyentes, exit 130es 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.

información relacionada