В чем разница между Ctrl-C и SIGINT? - PullRequest
26 голосов
/ 06 декабря 2011

Я отлаживал программу на Python, которая при получении исключения 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 ]

19 голосов
/ 07 декабря 2011

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

kill -SIGINT -<pid>

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

kill -SIGINT %
4 голосов
/ 06 декабря 2011

Как описано здесь :

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

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

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

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

это «съест» исключение KeyboardInterrupt.

...