В чем разница между 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.