What does "a signal for which a trap has been set" mean?
Esse é um sinal para o qual um manipulador foi definido (com trap 'handling code' SIG
) onde o código de manipulação não está vazio, pois isso faria com que o sinal fosse ignorado.
Portanto, os sinais que têm sua disposição padrão não são sinais para os quais uma armadilha foi definida. Algumas dessas citações em sua postagem também se aplicam a sinais que têm sua disposição padrão, embora obviamente não seja a parte sobre executar a armadilha , já que nenhuma armadilha foi definida para eles.
O manual fala sobre a entrega de sinal para o shell , não para os comandos que você executa a partir desse shell.
1.
If Bash is waiting for a command to complete and receives a signal for which a trap has been set, the trap will not be executed until the command completes.
(1)
why in my first example, does ctrl-C make the foreground job exit immediately before it can complete
Se você executar sleep 10
no prompt de um shell interativo , o shell colocará esse trabalho no primeiro plano (por meio de um ioctl()
no dispositivo tty que informa à disciplina de linha de terminal qual grupo de processos é o primeiro plano), então somente sleep
obterá uma SIGINT em ^C
e o shell interativo não , portanto não é útil testar esse comportamento .
-
O shell pai, como é interativo, não receberá o SIGINT, pois o processo não está no grupo de processos em primeiro plano.
-
Cada comando é livre para manipular sinais como bem entenderem.
sleep
não faz nada especialmente com o SIGINT, portanto, obterá a disposição padrão (terminar), a menos que o SIGINT esteja sendo ignorado na inicialização.
(2) Se você executar sleep 10
em um shell não interativo ,
bash -c 'sleep 10; echo "$?"'
O% não-interativo bash
shell e sleep
receberão o SIGINT quando você pressionar Ctrl-C.
Se bash
sair imediatamente, ele poderá deixar o comando sleep
em execução em segundo plano se ignorar ou manipular o sinal SIGINT. Então, ao invés disso,
-
bash
como a maioria dos outros shells, bloqueia a recepção de sinais (pelo menos alguns sinais) ao aguardar comandos. - A entrega é retomada depois que o comando sai (no qual as traps são executadas). Isso também evita que comandos em traps sejam executados simultaneamente com outros comandos.
Nesse exemplo acima, sleep
morrerá no SIGINT, portanto, bash
não demora muito para manipular seu próprio SIGINT (aqui para morrer, pois não adicionei um trap
no SIGINT).
(3) quando você pressiona Ctrl + C enquanto executa o shell não interativo:
bash -c 'sh -c "trap \"\" INT; sleep 3"; echo "$?"'
(sem trap
no SIGINT) bash
não é eliminado pelo SIGINT. bash
, como alguns outros shells tratam SIGINT e SIGQUIT especialmente. Eles implementam o comportamento espera e saída cooperativa descrito no link (e é conhecido por causar alguns aborrecimentos como os scripts chamando o SIGINT manipulando comandos que não podem ser interrompidos com ^C
)
(4) Para testar adequadamente, você deve executar um bash
não interativo que possui um conjunto de interceptações SIGINT e chamar um comando que não morra logo no SIGINT como:
bash -c 'trap "echo Ouch" INT; sh -c "trap \"\" INT; sleep 3"'
bash
está aguardando sh
que (juntamente com sleep
) SIGINT foi ignorado (por causa do trap "" INT
), portanto, o SIGINT não eliminará sleep
nem sh
. bash
não ignora o SIGINT, mas seu tratamento é adiado até que sh
retorne. Você verá Ouch
sendo exibido, não em Ctrl + C , mas após sleep
e sh
terem terminado normalmente.
Observe que o comando trap
define um trap para um sinal para o mesmo shell no qual ele é executado. Então, quando o comando trap
é executado fora do shell não interativo e no shell pai,
$ trap "echo You hit control-C!" INT $ bash -c 'sleep 10; echo "$?"' ^C $
os comandos não interativo bash
e sleep
não herdarão esse trap
do shell pai. Os manipuladores de sinal são perdidos ao executar um comando diferente ( execve()
apaga todo o espaço de endereço do processo, incluindo o código do manipulador). Após execve()
, os sinais que tinham um manipulador definido revertem para a disposição padrão, aqueles que foram ignorados permanecem ignorados.
Além disso, na maioria dos shells, trap
s também são resetados em sub-shells.
2.
When Bash is waiting for an asynchronous command via the wait builtin, the reception of a signal for which a trap has been set will cause the wait builtin to return immediately with an exit status greater than 128, immediately after which the trap is executed.
Ao usar wait
explicitamente , wait
é interrompido por qualquer sinal que tenha um conjunto de interceptações (e, obviamente, também aquelas que matam o shell completamente).
Isso torna difícil obter o status de saída de um comando de maneira confiável quando há sinais retidos :
$ bash -c 'trap "echo Ouch" INT; sh -c "trap \"\" INT; sleep 10" & wait "$!"; echo "$?"'
^COuch
130
Nesse caso, sleep
e sh
não foram mortos pelo SIGINT (já que eles o ignoram). Ainda wait
retorna com um status de saída 130
porque um sinal (SIGINT) foi recebido enquanto aguardava sh
. Você precisaria repetir o wait "$!"
até que sh
realmente terminasse para obter o status de saída de sh
.