Какие сигналы нельзя перехватить в linux
В вашей системе есть страница man, на которой перечислены все имеющиеся сигналы, но доступ к этой странице происходит по-разному в зависимости от того, какая у вас операционная систем. В большинстве систем Linux страницу можно открыть с помощью команды man 7 signal. Если возникнут проблемы, то найдите точное месторасположение страницы man с помощью команды
Сигналы в вашей командной оболочке Bash
Когда отсутствуют какие-либо команды trap, интерактивная оболочка Bash игнорирует сигналы SIGTERM и SIGQUIT. Сигнал SIGINT перехватывается и обрабатывается, и если осуществляется управление заданиями, то также игнорируются сигналы SIGTTIN, SIGTTOU и SIGTSTP. Если эти сигналы поступают от клавиатуры, то команды, участвующие в подстановке команд, также игнорируют эти сигналы.
По сигналу SIGHUP по умолчанию происходит выход из командной оболочки. Интерактивная оболочка отправит сигнал SIGHUP всем заданиям, работающим или остановленным; если вы хотите отменить такое действие для конкретного процесса, которое задается по умолчанию, смотрите документацию по встроенной команде disown. Во встроенной команде shopt укажите параметр huponexit для уничтожения всех заданий, принимающих сигнал SIGHUP.
Посылаем сигнал в командной оболочке
В оболочке Bash можно посылать следующие сигналы:
Таблица 12.1. Управляющие сигналы в Bash
| Стандартная комбинация клавиш | Значение | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
![]() | Настройки терминала | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Имя сигнала | Значение сигнала | Действие | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
![]() | SIGKILL и SIGSTOP | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Сигнал | Номер | Действие | Комментарий |
| терминалом, либо завершение управляющего | |||
| терминалом процесса | |||
| SIGINT | 2 | Term | Прерывание с клавиатуры |
| SIGQUIT | 3 | Core | Выход с клавиатуры |
| SIGILL | 4 | Core | Несуществующая инструкция |
| SIGABRT | 6 | Core | Сигнал аварии (abort), посланный |
| abort(3) | |||
| SIGFPE | 8 | Core | Ошибка операций с плавающей запятой |
| SIGKILL | 9 | Term | Kill-сигнал |
| SIGSEGV | 11 | Core | Некорректная ссылка в память |
| SIGPIPE | 13 | Term | Оборванный канал: запись в канал, |
| из которого не читают | |||
| SIGALRM | 14 | Term | Сигнал таймера, посланный alarm(2) |
| SIGTERM | 15 | Term | Сигнал завершения |
| SIGUSR1 | 30,10,16 | Term | Первый сигнал, определяемый |
| пользователем | |||
| SIGUSR2 | 31,12,17 | Term | Второй сигнал, определяемый |
| пользователем | |||
| SIGCHLD | 20,17,18 | Ign | Потомок остановлен или прекратил |
| выполнение | |||
| SIGCONT | 19,18,25 | Cont | Продолжить выполнение, если остановлен |
| SIGSTOP | 17,19,23 | Stop | Остановить выполнение процесса |
| SIGTSTP | 18,20,24 | Stop | Останов введён с терминала |
| SIGTTIN | 21,21,26 | Stop | Ввод с терминала у фонового процесса |
| SIGTTOU | 22,22,27 | Stop | Вывод на терминал у фонового процесса |
Сигналы SIGKILL и SIGSTOP нельзя поймать, заблокировать или проигнорировать.
Далее приведены сигналы, не входящие в POSIX.1-1990, но описанные в SUSv2 и POSIX.1-2001.
| Сигнал | Номер | Действие | Комментарий |
| доступа) | |||
| SIGPOLL | Term | Событие опроса (Sys V). | |
| Синоним SIGIO | |||
| SIGPROF | 27,27,29 | Term | Закончилось время профилирующего |
| таймера | |||
| SIGSYS | 12,31,12 | Core | Недопустимый аргумент для процедуры |
| (SVr4) | |||
| SIGTRAP | 5 | Core | Ловушка трассировки/отладки |
| SIGURG | 16,23,21 | Ign | Приоритетное состояние у сокета |
| (4.2BSD) | |||
| SIGVTALRM | 26,26,28 | Term | Виртуальный таймер (4.2BSD) |
| SIGXCPU | 24,24,30 | Core | Превышено время работы на ЦП (4.2BSD) |
| SIGXFSZ | 25,25,31 | Core | Превышен размер файла (4.2BSD) |
В Linux до версии 2.2 включительно поведением по умолчанию для сигналов SIGSYS, SIGXCPU, SIGXFSZ и SIGBUS (на всех архитектурах кроме SPARC и MIPS) было завершение процесса без создания дампа (в некоторых системах UNIX действием по умолчанию для SIGXCPU и SIGXFSZ является завершение процесса без создания дампа). Linux версии 2.4 соответствует требованиям POSIX.1-2001 для этих сигналов и завершает процесс с созданием дампа.
Некоторые другие сигналы.
| Сигнал | Номер | Действие | Комментарий |
| SIGEMT | 7,-,7 | Term | |
| SIGSTKFLT | -,16,- | Term | Ошибка стека на сопроцессоре |
| (не используется) | |||
| SIGIO | 23,29,22 | Term | Теперь возможен ввод/вывод (4.2BSD) |
| SIGCLD | -,-,18 | Ign | Синоним SIGCHLD |
| SIGPWR | 29,30,19 | Term | Отказ системы питания (System V) |
| SIGINFO | 29,-,- | Синоним SIGPWR | |
| SIGLOST | -,-,- | Term | Утрачена блокировка файла (не используется) |
| SIGWINCH | 28,28,20 | Ign | Сигнал изменения размера окна |
| (4.3BSD, Sun) | |||
| SIGUNUSED | -,31,- | Core | Синоним SIGSYS |
Сигнал с номером 29 на alpha соответствует SIGINFO / SIGPWR, а на sparc соответствует SIGLOST.
Сигнал SIGEMT не определён в POSIX.1-2001, но, тем не менее, появляется почти во всех системах UNIX, где действием по умолчанию для него является завершение процесса с созданием дампа.
Сигнал SIGPWR (не определён в POSIX.1-2001) по умолчанию, обычно, игнорируется (в других системах UNIX).
Для сигнала SIGIO (не определён в POSIX.1-2001) в других системах UNIX действием по умолчанию является игнорирование.
Если определён сигнал SIGUNUSED, то он является синонимом SIGSYS для большинства архитектур.
Сигналы реального времени
Ядро Linux поддерживает 33 таких сигнала, начиная с номера 32 до номера 64. Однако внутри реализации нитей POSIX в glibc используется два (для NPTL) или три (для LinuxThreads) сигнала реального времени (смотрите pthreads(7)), а значение SIGRTMIN корректируется должным образом (до 34 или 35). Так как диапазон доступных сигналов реального времени различается в зависимости от реализации нитей в glibc (и это может происходить во время выполнения при смене ядра и glibc), и, более того, диапазон сигналов реального времени различен в разных системах UNIX, то программы никогда не должны задавать сигналы реального времени по номерам, а вместо этого всегда должны записывать их в виде SIGRTMIN+n и выполнять проверку (во время выполнения), что SIGRTMIN+n не превышает SIGRTMAX.
В отличие от стандартных сигналов, сигналы реального времени не имеют предопределенного назначения: весь набор сигналов реального времени приложения могут использовать так, как им нужно.
Действием по умолчанию для необработанных сигналов реального времени является завершение процесса (terminate).
Сигналы реального времени отличаются от обычных в следующем:
1. В очередь можно добавлять несколько экземпляров одного сигнала реального времени. В случае со стандартными сигналами, если доставляется несколько экземпляров сигнала, в то время как этот тип сигнала в данный момент заблокирован, то только один экземпляр будет добавлен в очередь. 2. Если сигнал отправляется с помощью sigqueue(3), то с сигналом может быть отправлено некоторое значение (целочисленное, либо указатель). Если принимающий процесс устанавливает обработчик для сигнала, используя флаг SA_SIGINFO и вызов sigaction(2), то он может получить это значение через поле si_value структуры siginfo_t, переданной обработчику в виде второго аргумента. Кроме этого, поля si_pid и si_uid данной структуры можно использовать для получения идентификатора процесса и реального идентификатора пользователя, отправившего сигнал. 3. Сигналы реального времени доставляются точно в порядке поступления. Несколько сигналов одного типа доставляются в порядке, определяемых их отправлением. Если процессу отправлено несколько разных сигналов реального времени, то порядок их доставки начинается с сигнала с наименьшим номером (то есть сигналы с наименьшим номером имеют наивысший приоритет). Порядок же для стандартных сигналов в такой ситуации не определён.
Если процессу передан и стандартный сигнал, и сигнал реального времени, то в POSIX однозначно не определено, какой из них будет доставлен первым. В Linux, как и во многих других реализациях в таких случаях, отдан приоритет стандартным сигналам.
В соответствии с POSIX, реализация должна позволять ставить в очередь процесса как минимум _POSIX_SIGQUEUE_MAX (32) сигнала. Однако в Linux это делается по-другому. В ядрах до версии 2.6.7 включительно, Linux накладывает общесистемный лимит на количество сигналов режима реального времени в очереди для всех процессов. Этот лимит может быть получен и изменён (если есть права) через файл /proc/sys/kernel/rtsig-max. Текущее количество сигналов режима реального времени в очереди можно получить из файла /proc/sys/kernel/rtsig-nr. В Linux 2.6.8 данные интерфейсы /proc были заменены на ограничение ресурса RLIMIT_SIGPENDING, которое устанавливает ограничение на очередь сигналов на каждого пользователя отдельно; дополнительную информацию можно найти в setrlimit(2).
Для дополнительных сигналов или сигналов реального времени требуется расширение структуры набора сигналов (sigset_t) с 32 до 64 бит. В связи с этим, различные системные вызовы заменены на новые системные вызов, поддерживающие набор сигналов большего размера. Вот соответствие старых и новых системных вызовов:
| Linux 2.0 и старее | Linux 2.2 и новее |
| sigaction(2) | rt_sigaction(2) |
| sigpending(2) | rt_sigpending(2) |
| sigprocmask(2) | rt_sigprocmask(2) |
| sigreturn(2) | rt_sigreturn(2) |
| sigsuspend(2) | rt_sigsuspend(2) |
| sigtimedwait(2) | rt_sigtimedwait(2) |
Безопасные асинхронные функции при работе с сигналами
Функция обработки сигнала должна быть написана очень аккуратно, так как она может быть вызвана в любом месте работы программы. В POSIX есть понятие «безопасной функции». Если сигнал прерывает выполнение небезопасной функции или обработчик вызывает небезопасную функцию, то поведение программы не определено.
Согласно POSIX.1-2004 (также называемом POSIX.1-2001 Technical Corrigendum 2) от реализации требуется гарантировать, что следующие функции можно безопасно вызывать из обработчика сигнала:
В POSIX.1-2008 из списка выше удалены функции fpathconf(), pathconf() и sysconf() и добавлены следующие:
В POSIX.1-2008 Technical Corrigendum 1 (2013) добавлены следующие функции:
Прерывание системных вызовов и библиотечных функций обработчиками сигналов
Выбираемое поведение зависит от интерфейса и от того, был ли обработчик сигнала установлен с флагом SA_RESTART (смотрите sigaction(2)). Но в различных системах UNIX есть другие различия; далее описаны подробности для Linux.
Если заблокированный вызов к одному из следующих интерфейсов прерван обработчиком сигнала, то вызов будет автоматически перезапущен после завершения обработчика сигнала, если задействован флаг SA_RESTART; иначе вызов завершается с ошибкой EINTR:
* Вызовы read(2), readv(2), write(2), writev(2) и ioctl(2) для «медленных» устройств. «Медленным» называют устройство, которое может навсегда заблокировать ввод-вывод, например, терминал, канал или сокет. Если вызов ввода-вывода для медленного устройства уже передал немного данных на момент прерывания обработчиком сигнала, то вызов вернёт состояние успешного выполнения (обычно, количество переданных байт). Заметим, что диск (локальный) не подходит под определение медленного устройства; операции ввода-вывода с дисками не прерываются сигналами. * Вызов open(2), если он может выполнить блокировку (например, при открытии FIFO; смотрите fifo(7)). * Вызовы wait(2), wait3(2), wait4(2), waitid(2) и waitpid(2). * Интерфейсы сокетов: accept(2), connect(2), recv(2), recvfrom(2), recvmmsg(2), recvmsg(2), send(2), sendto(2) и sendmsg(2), если для сокета не указано время ожидания (смотрите далее). * Интерфейсы файловой блокировки: flock(2) и операции F_SETLKW и F_OFD_SETLKW у fcntl(2). * Интерфейсы очереди сообщений POSIX: mq_receive(3), mq_timedreceive(3), mq_send(3) и mq_timedsend(3). * Вызов futex(2) с FUTEX_WAIT (начиная с Linux 2.6.22; до этой версии вызов завершался с ошибкой EINTR). * getrandom(2). * pthread_mutex_lock(3), pthread_cond_wait(3) связанный с этим программный интерфейс. * futex(2) FUTEX_WAIT_BITSET. * Интерфейсы семафоров POSIX: sem_wait(3) и sem_timedwait(3) (начиная с Linux 2.6.22; до этой версии вызовы завершались с ошибкой EINTR).
Следующие интерфейсы никогда не перезапускаются после прерывания обработчиком сигнала независимо от наличия SA_RESTART; они всегда завершаются с ошибкой EINTR, если прерываются обработчиком сигнала:
Функция sleep(3) также никогда не перезапускается, если прервана обработчиком сигнала, но сообщает об успешном выполнении: возвращает количество оставшиеся для сна секунд.
Прерывание системных вызовов и библиотечных функций сигналами останова
Интерфейсы Linux, к которым это относится:
* «Входные» интерфейсы сокетов, если установлен таймаут (SO_RCVTIMEO) на сокете с помощью setsockopt(2): accept(2), recv(2), recvfrom(2), recvmmsg(2) (также с аргументом timeout, не равным NULL) и recvmsg(2). * «Выходные» интерфейсы сокетов, если установлен таймаут (SO_RCVTIMEO) на сокете с помощью setsockopt(2): connect(2), send(2), sendto(2) и sendmsg(2), если установлен таймаут отправления (SO_SNDTIMEO). * epoll_wait(2), epoll_pwait(2). * semop(2), semtimedop(2). * sigtimedwait(2), sigwaitinfo(2). * read(2) из файлового дескриптора inotify(7). * Linux версии 2.6.21 и более ранних: futex(2) FUTEX_WAIT, sem_timedwait(3), sem_wait(3). * Linux версии 2.6.8 и более ранних: msgrcv(2), msgsnd(2). * Linux версии 2.4 и более ранних: nanosleep(2).

