Ответ 1
Существует один случай, когда обработчик синтаксиса по умолчанию не установлен при запуске, и именно тогда маска сигнала содержит SIG_IGN
для SIGINT
при запуске программы. Код, отвечающий за это, можно найти здесь.
Маска сигнала игнорируемых сигналов наследуется от родительского процесса, а обработанные сигналы reset - SIG_DFL
. Поэтому в случае игнорирования SIGINT
условие if (Handlers[SIGINT].func == DefaultHandler)
в источнике не запускается, а обработчик по умолчанию не установлен, python не переопределяет настройки, выполненные родительским процессом в этом случае.
Итак, попробуйте показать обработчик использованного сигнала в разных ситуациях:
# invocation from interactive shell
$ python -c "import signal; print(signal.getsignal(signal.SIGINT))"
<built-in function default_int_handler>
# background job in interactive shell
$ python -c "import signal; print(signal.getsignal(signal.SIGINT))" &
<built-in function default_int_handler>
# invocation in non interactive shell
$ sh -c 'python -c "import signal; print(signal.getsignal(signal.SIGINT))"'
<built-in function default_int_handler>
# background job in non-interactive shell
$ sh -c 'python -c "import signal; print(signal.getsignal(signal.SIGINT))" &'
1
Итак, в последнем примере SIGINT
установлено значение 1 (SIG_IGN
). Это то же самое, что и при запуске фонового задания в оболочке script, поскольку по умолчанию они не являются интерактивными (если вы не используете параметр -i
в shebang).
Таким образом, это вызвано тем, что оболочка игнорирует сигнал при запуске фонового задания в неинтерактивном сеансе оболочки, а не непосредственно с помощью python. По крайней мере bash
и dash
ведут себя так, я не пробовал другие оболочки.
Существует два варианта решения этой проблемы:
-
вручную установите обработчик сигнала по умолчанию:
import signal signal.signal(signal.SIGINT, signal.default_int_handler)
-
добавьте параметр
-i
к shebang оболочки script, например:#!/bin/sh -i
edit: это поведение описано в руководстве bash:
СИГНАЛЫ
...
Когда управление заданиями не действует, асинхронные команды игнорируют SIGINT и SIGQUIT в дополнение к этим унаследованным обработчикам.
который применяется к неинтерактивным оболочкам, поскольку по умолчанию они отключены, и на самом деле они указаны в POSIX: Командный язык оболочки