В чем разница между Ctrl-C и SIGINT?

Я отлаживал программу Python, которая segfaults после получения KeyboardInterrupt исключения. Обычно это делается нажатием кнопки Ctrl+C из оболочки. Чтобы проверить, исправила ли ошибка конкретное изменение кода, у меня был небольшой shell-скрипт, который отправил SIGINT к программе в произвольное время после запуска. Проблема у меня в том, что отправка Ctrl+C кажется, имеет другое влияние на программу, чем отправка сигнала SIGINT и, таким образом, не вызывает ошибку появляются, поэтому мне очень интересно, в чем разница между этими двумя действиями.

программа не улавливает никаких действий клавиатуры вообще, и это просто программа python с некоторыми потоками / процессами в них. Он не устанавливает обработчики сигналов (хотя Python делает), и stty -a дает intr = ^C. Я подозреваю, что это может быть, что Ctrl+C передает SIGINT для всех подпроцессов / потоков в то время как kill -INT только отправляет в основной процесс, но это пока мои подозрения идти.

вот сценарий оболочки, который отправляет 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

2 ответов


^C передает SIGINT для всех процессов в группе процессов переднего плана. Сделать эквивалент с kill, вы должны отправить сигнал в группу процессов (концепция уровня ОС):

kill -SIGINT -<pid>

или к заданию (концепция уровня оболочки, конвейер закончился на &):

kill -SIGINT %

As описано здесь :

Python устанавливает небольшое количество обработчиков сигналов по умолчанию: SIGPIPE игнорируется (поэтому ошибки записи на трубах и сокетах можно сообщить как обычные исключения Python), а SIGINT переводится в Исключение KeyboardInterrupt. Все это можно отменить.

таким образом, поведение должно быть одинаковым между отправкой SIGINT и Ctrl + c.

но, вы должны быть осторожны с KeyboardInterrupt, если где-то в коде у вас есть

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

это будет "есть" исключение KeyboardInterrupt.