Pergunta

Posso escrever scripts de shell que capturam SIGINT perfeitamente, mas não consigo capturar SIGQUIT.

#!/bin/bash

function die {
    echo "Dying on signal $1"
    exit 0
}

trap 'die "SIGINT"' SIGINT
trap 'die "SIGQUIT"' SIGQUIT

while true; do
    echo "sleeping..."
    sleep 5
done

Executar este script e pressionar CTRL-C tem o efeito desejado, mas pressionar CTRL-\ (que, pelo que entendi, deve acionar SIGQUIT) não faz nada, exceto imprimir ^\ no terminal. Por quê?

Tenho duas teorias em execução. A primeira é que a semântica de SIGINT e SIGQUIT são diferentes, de modo que SIGQUIT só é enviado para o processo filho sleep, enquanto SIGINT é enviado para o processo filho e o processo bash pai. Se for esse o caso, onde está documentado?

Minha segunda teoria é que o bash não apenas ignora (ou seja, tem um manipulador autônomo para) SIGQUIT por padrão (como a página do manual sugere), mas também não permite que seja interceptado. Essa teoria se sobrepõe à primeira, já que pode ser o caso de SIGQUIT indo para o pai e o filho, mas o pai (bash) simplesmente não consegue prendê-lo. Se for esse o caso, há alguma maneira de capturar SIGQUIT em um script bash? ... talvez algum shopt que eu possa definir?

Editar: isto é no Ubuntu 10.10 no gnome-terminal 2.32.0 executando o bash 4.1.5, e sim ^\ está configurado para emitir SIGQUIT (conforme relatado por stty -a e confirmado pela emissão de ^\ SIGQUITs para outros programas como ping).

ATUALIZAÇÃO: Acabei de descobrir que o problema deve ser devido ao gnome-terminal. Se eu executar este script a partir de um console virtual (ou seja, ctrl-alt-f1 para sair do X), ele intercepta SIGQUIT perfeitamente bem quando pressiono ^\. Mesmo bash e tudo, então a única diferença deve ser o emulador de terminal. Então agora minha pergunta é: como posso configurar o gnome-terminal para se comportar como o console virtual a esse respeito? Eu diff'd as saídas de stty -a no console virtual e no gnome-terminal e, embora haja diferenças, nada parece imediatamente relevante (por exemplo, ambos têm quit = ^\;).

ATUALIZAÇÃO 2: Outro experimento. Simplesmente execute $ sleep 60 no gnome-terminal; pressione ^\ e o sinal não será capturado. Agora execute $ sleep 60 no console virtual; pressione ^\ e o sinal é capturado - o processo imprime Quit e sai. Mas agora execute $ ping google.com no gnome-terminal e pressione ^\ - o sinal é capturado e tratado conforme o esperado. Portanto, há algo estranho no gnome-terminal de tal forma que o SIGQUIT pode ser capturado por alguns programas, mas não por outros, mesmo que esses outros o façam o capturem quando invocados do console virtual. Talvez eu deva apenas atualizar meu terminal gnome.

Foi útil?

Solução

Só posso presumir que era algum tipo de bug no gnome-terminal 2.32.0;Desde então, atualizei para o Ubuntu 11.04, com gnome-terminal 2.32.1 (e bash 4.2.8) e SIGQUIT agora está preso como esperado.

Outras dicas

Eu observo o mesmo comportamento no Fedora 19 com XFCE: de acordo com ps s, bash no terminal xfce4 tem SIGQUIT ignorado, executando yes >/dev/null & e então ps s mostra que mesmo um subprocesso tem SIGQUIT ignorado.Quando eu (do mesmo terminal) executo ssh localhost, o shell na sessão ssh também tem SIGQUIT ignorado, mas yes >/dev/null & não.

Dado o comentário acima que menciona o gnome-terminal, acho que o bug está na parte comum dos dois terminais: a biblioteca vte.O meu é vte-0.28.2-9.fc19.x86_64.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top