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

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

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

Eu tenho um launch.shscript que inicia o process.sh.

lançamento.sh

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

processo.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 então mate-o com

kill -s SIGINT -$!    

onde $!pega o PID do último comando (launch.sh) e o sinal de menos envia o sinal para todos os filhos, depois launch.shcontinua. Por que?


Eu esperava o seguinte comportamento (de acordo com este blogSinal e Bash) :

o shell A com o script launch.shem execução em segundo plano é interrompido, o Bash espera até process.shterminar. Como process.shretorna anormalmente (saída 130) devido ao manipulador de sinal em process.sh, o shell A deve sair. Por que não?

Se o status desse filho indicar que ele saiu de forma anormal devido a esse sinal, o shell limpa, remove seu manipulador de sinal e se mata novamente para acionar a ação padrão do sistema operacional (saída anormal). Alternativamente, ele executa o manipulador de sinal do script conforme definido com trap e continua.

Responder1

Primeiro, exit 130não é uma saída anormal. É uma saída normal, com status de saída 130. Como pode ser visto emman 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.

WIFEXITEDverifica a saída normal e WIFSIGNALLEDé encerrado devido a um sinal não capturado. Como estes são mutuamente exclusivos, an exit 130é normal.

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

Segundo, um processo que lida com SIGINT e depois morre deve se matar com SIGINT. O wiki de Greg (um excelente recurso para coisas de shell) temuma nota sobre isso:

Se você optar por configurar um manipulador para SIGINT (em vez de usar a armadilha EXIT), você deve estar ciente de que um processo que sai em resposta a SIGINT devematar-se com SIGINTem vez de simplesmente sair, para evitar causar problemas ao chamador. Por isso:

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

Agora, se você mudou exit 130para:

trap - INT
kill -INT $$

Você veria o comportamento esperado.

informação relacionada