Процессы могут выбрать:
- игнорировать сигнал SIGINT, обычно отправляемый при нажатии Ctrl-C(как
trap '' INTв оболочке), или иметь собственный обработчик для него, который решает не завершаться (или не завершается своевременно).
- сообщить терминальному устройству, что символ, который вызывает отправку SIGINT на задание переднего плана, является чем-то другим (как
stty int '^K'в оболочке)
- скажите терминальному устройству не отправлять какой-либо сигнал (как
stty -isigв оболочке).
Или они могут быть бесперебойными, как, например, в середине системного вызова, который не может быть прерван.
В Linux (с относительно новым ядром) вы можете определить, игнорирует ли процесс и / или обрабатывает ли SIGINT, посмотрев вывод
$ kill -l INT
2
$ grep Sig "/proc/$pid/status"
SigQ: 0/63858
SigPnd: 0000000000000000
SigBlk: 0000000000000000
SigIgn: 0000000000000002
SigCgt: 0000000000000000
SIGINT равен 2. Второй бит SigIgn выше равен 1, что означает, что SIGINT игнорируется.
Вы можете автоматизировать это с:
$ SIG=$(kill -l INT) perl -lane 'print $1 if $F[0] =~ /^Sig(...):/ &&
$F[1] & (1<<($ENV{SIG}-1))' < "/proc/$pid/status"
Ign
Чтобы проверить, что является текущим intrсимволом или isigвключено ли для данного терминала:
$ stty -a < /dev/pts/0
[...] intr = ^C [...] isig
(над intrсимволом ^C(символ, обычно отправляемый вашим терминалом (эмулятором) при нажатии CTRL-Cи входные сигналы не отключаются.
$ stty -a < /dev/pts/1
[...] intr = ^K [...] -isig
( intrсимвол есть ^Kи isigотключен для /dev/pts/1).
Для полноты, есть два других способа, которыми процесс может что-то предпринять, чтобы прекратить получать SIGINT, хотя это обычно не так.
После Ctrl+Cэтого сигнал SIGINT отправляется всем процессам в группе процессов переднего плана терминала . Обычно это оболочка, которая помещает процессы в группы процессов (сопоставленные с заданиями оболочки ) и сообщает терминальному устройству, которое является приоритетным .
Теперь процесс может:
Оставьте свою процессную группу. Если он перемещается в другую группу процессов (любую группу процессов, кроме той, которая является приоритетной ), он больше не будет получать Ctrl-Cсигнал SIGINT (как и другие связанные с клавиатурой сигналы, такие как SIGTSTP, SIGQUIT). Однако он может быть приостановлен, если попытается выполнить чтение (возможно, запись также в зависимости от настроек терминального устройства) с терминального устройства (как это делают фоновые процессы).
В качестве примера:
perl -MPOSIX -e 'setpgid(0,getppid) or die "$!"; sleep 10'
не может быть прервана с Ctrl-C. Выше perlбудет попытаться присоединиться к группе процессов, чей идентификатор совпадает с идентификатором его родительского процесса. В общем, нет никакой гарантии, что будет такая группа процессов с таким идентификатором. Но здесь, в случае, если эта perlкоманда запускается самостоятельно по приглашению интерактивной оболочки, ppid будет процессом оболочки, и оболочка обычно запускается в своей собственной группе процессов.
Если команда еще не является лидером группы процессов (лидером этой группы процессов переднего плана), то запуск новой группы процессов будет иметь тот же эффект.
Например, в зависимости от оболочки,
$ ps -j >&2 | perl -MPOSIX -e 'setpgid(0,0) or die "$!"; sleep 10'
PID PGID SID TTY TIME CMD
21435 21435 21435 pts/12 00:00:00 zsh
21441 21441 21435 pts/12 00:00:00 ps
21442 21441 21435 pts/12 00:00:00 perl
будет иметь такой же эффект. psи perlзапускаются в группе процессов переднего плана, но в большинстве оболочек psбудет лидером этой группы (как видно из psрезультатов выше, где pgid обоих psи perlpid ps), поэтому perlможет запускать свою собственную группу процессов.
Или это может изменить группу процессов переднего плана. В основном, скажите tty устройству отправить SIGINT какой-либо другой группе процессов послеCtrl+C
perl -MPOSIX -e 'tcsetpgrp (0, getppid) или умереть $ !; спать 5 '
Там perlостается в той же группе процессов, но вместо этого сообщает оконечному устройству, что приоритетной группой процессов является та, чей идентификатор совпадает с идентификатором его родительского процесса (см. Примечание выше об этом).
kill -9 %убить их. Сигнал 9 нельзя игнорировать, как и сигнал приостановки. Последовательность клавиш CTRL + Z можно игнорировать в теории, но не на практике.