Подтвердить что ты не робот

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

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

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

Вот оболочка script, которая отправляет 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
4b9b3361

Ответ 1

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

kill -SIGINT -<pid>

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

kill -SIGINT %

Ответ 2

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

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

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

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

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

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