bash não sai na saída anormal do processo filho devido ao sinal

6

Eu tento realmente entender o que estou fazendo errado e por quê?

Eu tenho um script launch.sh que inicia process.sh .

launch.sh

#!/bin/bash
while true; do 
./process.sh 
done

process.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

quando eu corro

./launch.sh &

e, em seguida, mate-o com

kill -s SIGINT -$!    

onde $! obtém o PID do último comando (launch.sh) e o menos envia o sinal para todos os filhos, então launch.sh continua. Por quê?

Eu esperava o seguinte comportamento (de acordo com este blog Signal & Bash ):

o shell A com o script launch.sh sendo executado em segundo plano é interrompido, o Bash aguarda até que process.sh termine. Como process.sh retorna anormalmente (saída 130) devido ao manipulador de sinal em process.sh , o shell A deve sair. Por que não?

If this child’s status indicates it exited abnormally due to that signal, the shell cleans up, removes its signal handler, and kills itself again to trigger the OS default action (abnormal exit). Alternatively, it runs the script’s signal handler as set with trap, and continues.

    
por Gabriel 17.02.2016 / 01:20

1 resposta

5

Primeiro, exit 130 não é uma saída anormal. É uma saída normal, com status de saída 130. Como pode ser visto em man 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 verifica a saída normal e WIFSIGNALLED é a finalização devido a um sinal não detectado. Como esses são mutuamente exclusivos, um exit 130 é normal.

O status de saída é 130 quando um processo é encerrado por SIGINT é porque o bash o configura como 130 fora do processo porque detectou uma saída devido a SIGINT: Por que o bash define $? (status de saída) para diferente de zero em Ctrl-C ou Ctrl-Z?

Em segundo lugar, um processo que manipula SIGINT e depois morre deve se matar com SIGINT. O wiki de Greg (um excelente recurso para shell) tem uma nota sobre isso :

If you choose to set up a handler for SIGINT (rather than using the EXIT trap), you should be aware that a process that exits in response to SIGINT should kill itself with SIGINT rather than simply exiting, to avoid causing problems for its caller. Thus:

trap 'rm -f "$tempfile"; trap - INT; kill -INT $$' INT

Agora, se você alterou o exit 130 para:

trap - INT
kill -INT $$

Você veria o comportamento esperado.

    
por 17.02.2016 / 01:49