Quando executo sleep
manualmente e, em seguida kill -INT
, o sono sai imediatamente. Por exemplo:
$ /bin/sleep 60 &
[1] 4002356
$ kill -INT 4002356
[1]+ Interrupt /bin/sleep 60
$ ps -C sleep
PID TTY TIME CMD
$
No entanto, quando faço a mesma coisa em um script de shell, sleep
ignoro o arquivo SIGINT
. Por exemplo:
set -o xtrace
echo
/bin/sleep 10 &
child="$!"
/bin/sleep 0.1
ps -C sleep
kill -TERM "$child" # SIGTERM
/bin/sleep 0.1
ps -C sleep
wait "$child" # will return immediately
echo
/bin/sleep 10 &
child="$!"
/bin/sleep 0.1
ps -C sleep
kill -INT "$child" # SIGINT
/bin/sleep 0.1
ps -C sleep
wait "$child" # will wait for 9.8 seconds
Por que/como o sleep ignora SIGINT
quando executo sleep
dentro de um script de shell?
Eu obtenho o mesmo comportamento com dash
e bash
. Meu kernel é Linux 5.4.0.
Responder1
Na /bin/sleep 10 &
finalização &
faz com que o shell seja executado sleep
de forma assíncrona. O controle de trabalho está desabilitado por padrão em um script. No Bash aplica-se o seguinte [ênfase minha]:
Comandos não integrados iniciados pelo Bash têm manipuladores de sinal definidos com os valores herdados pelo shell de seu pai.Quando o controle do trabalho não está em vigor, os comandos assíncronos ignoram o SIGINTe SIGQUIT além desses manipuladores herdados.
Fonte:Manual de referência do Bash.
E, da mesma forma, SIG_IGN
persiste em uma chamada para execv()
, com a possível exceção de SIGCHLD
.
Os sinais definidos para a ação padrão (SIG_DFL) na imagem do processo de chamada devem ser definidos para a ação padrão na nova imagem do processo. Exceto para SIGCHLD, os sinais configurados para serem ignorados (SIG_IGN) pela imagem do processo chamador devem ser configurados para serem ignorados pela nova imagem do processo. Os sinais definidos para serem capturados pela imagem do processo de chamada devem ser definidos para a ação padrão na nova imagem do processo (consulte <signal.h>).
Fonte:Especificações básicas do Open Group, edição 7, edição de 2018.