ti-enxame.com

Qual é a diferença entre Ctrl-C e SIGINT?

Estou depurando um programa Python que segfaults após receber uma exceção KeyboardInterrupt. Isso normalmente é feito pressionando Ctrl+C da Shell. Para testar se uma alteração de código específica corrigiu o bug, eu tinha um pequeno script do Shell que enviava SIGINT para o programa aleatoriamente após a inicialização. O problema que tenho é que enviar Ctrl+C parece ter um efeito diferente no programa do que enviar o sinal SIGINT e, portanto, não está causando o aparecimento do bug, por isso me pergunto qual é a diferença entre as duas ações.

O programa não captura nenhuma ação do teclado e é apenas um programa python com alguns threads/processos neles. Ele não instala manipuladores de sinal (embora Python = does) e stty -aintr = ^C. Eu suspeito que pode ser que Ctrl+C envia SIGINT para todos os subprocessos/threads enquanto kill -INT envia apenas para o processo primário, mas isso é até onde minhas suspeitas vão.

Aqui está o script do Shell que envia o kill -INT.

wait
while :; do
    seconds="$(python -c 'import random; print random.random()*4')"
    ./mandos --debug --configdir=confdir \
             --statedir=statedir --no-restore --no-dbus &
    pid=$!
    { sleep $seconds; kill -INT $pid; } &
    fg %./mandos
    status=$?
    if [ $status -gt 1 ]; then
        echo "Failed exit $status after $seconds seconds"
        break
    fi
    wait
done
28
Belorn

^C envia um SIGINT para todos os processos no grupo de processos em primeiro plano. Para fazer o equivalente a kill, você deve enviar o sinal ao grupo de processos (conceito no nível do SO):

kill -SIGINT -<pid>

ou para o trabalho (conceito em nível de shell, o pipeline terminou com &):

kill -SIGINT %
20
ninjalj

Como descrito aqui :

Por padrão, o Python instala um pequeno número de manipuladores de sinal: o SIGPIPE é ignorado (os erros de gravação nos tubos e soquetes podem ser relatados como comuns Python) e o SIGINT é convertido em uma exceção KeyboardInterrupt. estes podem ser substituídos.

portanto, o comportamento deve ser o mesmo entre enviar um SIGINT e um Ctrlc.

Mas você precisa ter cuidado com o KeyboardInterrupt, se em algum lugar do seu código você tiver um

try:
   ...
except:   # notice the lack of exception class
   pass

isso "comerá" a exceção KeyboardInterrupt.

4
Cédric Julien