Процессы могут выбрать:
- игнорировать сигнал 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
и perl
pid ps
), поэтому perl
может запускать свою собственную группу процессов.
Или это может изменить группу процессов переднего плана. В основном, скажите tty устройству отправить SIGINT какой-либо другой группе процессов послеCtrl+C
perl -MPOSIX -e 'tcsetpgrp (0, getppid) или умереть $ !; спать 5 '
Там perl
остается в той же группе процессов, но вместо этого сообщает оконечному устройству, что приоритетной группой процессов является та, чей идентификатор совпадает с идентификатором его родительского процесса (см. Примечание выше об этом).
kill -9 %
убить их. Сигнал 9 нельзя игнорировать, как и сигнал приостановки. Последовательность клавиш CTRL + Z можно игнорировать в теории, но не на практике.