Scroll to navigation

SIGACTION(2) Руководство программиста Linux SIGACTION(2)

ИМЯ

sigaction - получает и изменяет обработчик сигнала

ОБЗОР

#include <signal.h>

int sigaction(int signum, const struct sigaction *act,
              struct sigaction *oldact);


Требования макроса тестирования свойств для glibc (см. feature_test_macros(7)):

sigaction(): _POSIX_C_SOURCE >= 1 || _XOPEN_SOURCE || _POSIX_SOURCE

ОПИСАНИЕ

Системный вызов sigaction() используется для изменения выполняемого процессом действия при получении определённого сигнала (список сигналов смотрите в signal(7)).

В signum указывается сигнал; может принимать значение любого корректного сигнала за исключением SIGKILL и SIGSTOP.

Если значение act не равно NULL, то устанавливается новое действие для сигнала signum из act. Если значение oldact не равно NULL, то предыдущее действие записывается в oldact.

Структура sigaction определена следующим образом:


struct sigaction {

void (*sa_handler)(int);
void (*sa_sigaction)(int, siginfo_t *, void *);
sigset_t sa_mask;
int sa_flags;
void (*sa_restorer)(void); };

Для некоторых архитектур используется union: не выполняйте назначение одновременно sa_handler и sa_sigaction.

Элемент sa_restorer устарел и не должен использоваться. В POSIX не указан элемент sa_restorer.

sa_handler указывает действие, которое должно быть связано с signum; может принимать значение SIG_DFL в качестве действия по умолчанию, SIG_IGN, чтобы игнорировать этот сигнал, или принимать указатель на функцию управления сигналом. Данная функция получает номер сигнала в качестве своего единственного аргумента.

Если в sa_flags указан SA_SIGINFO, то sa_sigaction (вместо sa_handler) задаёт функцию обработки сигнала signum. В первом аргументе функция принимает номер сигнала, во втором — указатель на siginfo_t и в третьем — указатель на ucontext_t (приведённый к void *) (вообще, функция-обработчик не используется третий аргумент. Подробней о ucontext_t смотрите в getcontext(2)).

В sa_mask задаётся маска сигналов, которые должны блокироваться (т.е. добавляется к маске сигналов нити, в которой вызывается обработчик сигнала) при выполнении обработчика сигнала. Также будет блокироваться и сигнал, вызвавший запуск обработчика, если только не был использован флаг SA_NODEFER.

В flag указывается набор флагов, которые изменяют поведение сигнала. Он формируется побитовым ИЛИ из следующих флагов:

Если значение signum равно SIGCHLD, то уведомление об остановке дочернего процесса (т.е., в тех случаях, когда дочерний процесс получает сигнал SIGSTOP, SIGTSTP, SIGTTIN или SIGTTOU) или возобновлении работы (т.е., когда дочерний процесс получает SIGCONT) не будет получено (см. wait(2)). Этот флаг имеет значение только когда установлен обработчик SIGCHLD.
Если значение signum равно SIGCHLD, то дочерние процессы не будут переводиться в состояние зомби при завершении. Смотрите также waitpid(2). Этот флаг имеет значение только когда установлен обработчик SIGCHLD или когда обработчик сигнала установлен в SIG_DFL.

Если флаг SA_NOCLDWAIT не задан при установке обработчика SIGCHLD, то по POSIX.1 остаётся неопределённым, будет ли генерироваться сигнал SIGCHLD при завершении дочернего процесса. В Linux сигнал SIGCHLD в этом случае генерируется; в некоторых других реализациях это не делается.

Не препятствовать получению сигнала при его обработке обработчиком сигнала. Этот флаг имеет значение только когда установлен обработчик. Флаг SA_NOMASK является устаревшим синонимом данного флага.
Вызывать обработчик сигнала в дополнительном стеке сигналов, предоставленном sigaltstack(2). Если дополнительный стек недоступен, то будет использован стек по умолчанию. Этот флаг имеет значение только когда установлен обработчик.
Восстановить поведение сигнала после однократного вызова обработчика. Этот флаг имеет значение только когда установлен обработчик. Флаг SA_ONESHOT является устаревшим синонимом данного флага.
Обеспечивать поведение совместимое с семантикой сигналов BSD, позволяя некоторым системным вызовам перезапускаться в то время, как идет обработка сигналов. Этот флаг имеет значение только когда установлен обработчик. О перезапуске системных вызовов смотрите в signal(7).
Обработчик сигнала требует 3-х аргументов, а не одного. В этом случае надо использовать параметр sa_sigaction вместо sa_handler. Этот флаг имеет значение только когда установлен обработчик.

Аргумент siginfo_t в sa_sigaction представляет собой структуру из следующих элементов:


siginfo_t {

int si_signo; /* Номер сигнала */
int si_errno; /* Значение errno */
int si_code; /* Код сигнала */
int si_trapno; /* Номер ловушки, которую вызвал
аппаратный сигнал
(не используется для большинства
архитектур) */
pid_t si_pid; /* Идентификатор процесса, пославшего
сигнал */
uid_t si_uid; /* Реальный идентификатор пользователя
процесса, пославшего сигнал */
int si_status; /* Выходное значение или номер сигнала */
clock_t si_utime; /* Использованное пользовательское время */
clock_t si_stime; /* Использованное системное время */
sigval_t si_value; /* Значение сигнала */
int si_int; /* Сигнал POSIX.1b */
void *si_ptr; /* Сигнал POSIX.1b */
int si_overrun; /* Счётчик переполнения таймера; таймеры
POSIX.1b */
int si_timerid; /* Идентификатор таймера; таймеры
POSIX.1b */
void *si_addr; /* Адрес в памяти, приводящий к ошибке */
long si_band; /* Внутреннее событие (было int в
glibc 2.3.2 и более ранних */
int si_fd; /* Файловый дескриптор */
short si_addr_lsb; /* Наименее значимый бит адреса
(начиная с ядра 2.6.32) */ }

Поля si_signo, si_errno и si_code определены для всех сигналов. (si_errno обычно не используется в Linux.) Оставшаяся часть структуры может представлять собой объединение, поэтому нужно читать только те поля, которые имеют смысл для заданного сигнала:

  • Для сигналов, посылаемых kill(3) и sigqueue(3), заполняются si_pid и si_uid. Также для сигналов, посылаемых sigqueue(3), заполняются si_int и si_ptr значениями, задаваемыми отправителем сигнала; подробней смотрите sigqueue(3).
  • Для сигналов, посылаемых таймерами POSIX.1b (начиная с Linux 2.6), заполняются si_overrun и si_timerid. Поле si_timerid является внутренним идентификатором, который используется ядром для различения таймеров; это не идентификатор таймера, возвращаемого timer_create(2). Поле si_overrun отражает счётчик превышения таймера; эту же информацию можно получить с помощью вызова timer_getoverrun(2). Эти поля являются нестандартным расширением Linux.
  • Для сигналов, посылаемых уведомлением очереди сообщений (см. описание SIGEV_SIGNAL в mq_notify(3)), заполняются si_int/si_ptr значением sigev_value, предоставляемым mq_notify(3); si_pid — значением идентификатора процесса, отправившего сообщение; si_uid — значением реального идентификатора пользователя, отправившего сообщение.
  • Для SIGCHLD заполняются si_pid, si_uid, si_status, si_utime и si_stime, предоставляющие информацию о потомке. В поле si_pid указывается идентификатор процесса потомка; в si_uid — реальный пользовательский идентификатор потомка. В поле si_status содержится код завершения потомка (если si_code равно CLD_EXITED) или номер сигнала, который вызвал изменение состояния процесса. Поля si_utime и si_stime содержат системное и пользовательское время ЦП, затраченное процессом-потомком; эти поля не содержат время, использованное на ожидание потомков (в отличие от getrusage(2) и time(2)). В ядрах до версии 2.6 и начиная с 2.6.27 эти поля содержат время ЦП в единицах sysconf(_SC_CLK_TCK). В ядрах 2.6 до 2.6.27 ошибочно считалось, что эти поля содержат время в единицах (настраиваемых) системных мигов (jiffy) (см. time(7)).
  • Для SIGILL, SIGFPE, SIGSEGV, SIGBUS и SIGTRAP заполняется поле si_addr адресом ошибки. Для некоторых архитектур эти сигналы также заполняют поле si_trapno. Некоторые отдельные варианты SIGBUS, в частности BUS_MCEERR_AO и BUS_MCEERR_AR, также заполняют si_addr_lsb. Это поле указывает наименее значимый бит сообщаемого адреса и поэтому показывает размер повреждения. Например, если была повреждена страница целиком, то si_addr_lsb содержит log2(sysconf(_SC_PAGESIZE)). BUS_MCERR_* и si_addr_lsb являются расширениями Linux.
  • Для SIGIO/SIGPOLL (синонимы в Linux) заполняются si_band и si_fd. Событие si_band представляет собой битовую маску, содержащую те же значения, которые заполняются в поле revents вызовом poll(2). Поле si_fd содержит файловый дескриптор, для которого произошло событие ввода-вывода.

В поле si_code содержится значение (не маска битов), определяющее причину отправки сигнала. В следующей таблице приведены значения, которые могут быть в si_code для любого сигнала вместе с причиной возникновения сигнала:

kill(2)
посылается ядром
sigqueue(3)
таймер POSIX истёк
изменилось состояние очереди сообщений POSIX (начиная с Linux 2.6.6); см. mq_notify(3)
AIO завершён
Queued SIGIO (только в ядрах до Linux 2.2; начиная с Linux 2.4 SIGIO/SIGPOLL заполняют si_code как описано выше).
tkill(2) или tgkill(2) (начиная с Linux 2.4.19)

Следующие значения могут присутствовать в si_code для сигнала SIGILL:

некорректный код инструкции
некорректный операнд
некорректный режим адресации
некорректная ловушка
привилегированная операция
привилегированный регистр
ошибка сопроцессора
внутренняя ошибка стека

Следующие значения могут присутствовать в si_code для сигнала SIGFPE:

деление на ноль при работе с целыми числами
переполнение при работе с целыми числами
деление на ноль при работе с числами с плавающей запятой
переполнение при работе с числами с плавающей запятой
нехватка значения при работе с числами с плавающей запятой
неточный результат при работе с числами с плавающей запятой
неправильная операция при работе с числами с плавающей запятой
индекс вне разрешенных пределов при работе с числами с плавающей запятой

Следующие значения могут присутствовать в si_code для сигнала SIGSEGV:

адрес не соответствует объекту
некорректные права на отображённый объект

Следующие значения могут присутствовать в si_code для сигнала SIGBUS:

некорректное выравнивание адреса
несуществующий физический адрес
аппаратная ошибка, специфичная для объекта
машинной проверкой устранена аппаратная ошибка памяти; требуется действие
в процессе обнаружена аппаратная ошибка памяти, но не устранена; действие не обязательно

Следующие значения могут присутствовать в si_code для сигнала SIGTRAP:

точка останова процесса
ловушка отладки процесса
процесс пойман в ветвь ловушки
аппаратная точка прерывания/слежения

Следующие значения могут присутствовать в si_code для сигнала SIGCHLD:

дочерний процесс завершил работу
работа дочернего процесса была прервана (killed)
дочерний процесс завершился некорректно
сработала ловушка в отлаживаемом дочернем процессе
дочерний процесс остановлен
остановленный дочерний процесс продолжил работу (начиная с Linux 2.6.9)

Следующие значения могут присутствовать в si_code для сигнала SIGIO/SIGPOLL:

есть входные данные
освободились выходные буферы
есть входное сообщение
ошибка ввода-вывода
есть входные данные высокого приоритета
устройство отключено

ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ

При успешном выполнении sigaction() возвращает 0 и -1 при ошибке.

ОШИБКИ

act или oldact указывают на память, которая не является частью адресного пространства процесса.
Указан некорректный сигнал. Также ошибка будет сгенерирована, если произведена попытка изменить действие для сигналов SIGKILL или SIGSTOP, которые не могут быть перехвачены или игнорированы.

СООТВЕТСТВИЕ СТАНДАРТАМ

POSIX.1-2001, SVr4.

ЗАМЕЧАНИЯ

Потомок, созданный с помощью fork(2), наследует реакцию на сигналы от своего родителя. При execve(2) реакция на сигналы устанавливается в значение по умолчанию; реакция на игнорируемые сигналы не изменяется.

В соответствии с POSIX поведение процесса после игнорирования сигнала SIGFPE, SIGILL или SIGSEGV не определено, если эти сигналы не были посланы при помощи функций kill(2) или raise(3). Деление целого числа на ноль имеет непредсказуемый результат. В некоторых архитектурах это приводит к появлению сигнала SIGFPE. (Также, деление самого большого по модулю отрицательного числа на -1 тоже может приводить к SIGFPE.) Игнорирование этого сигнала может привести к появлению бесконечного цикла.

POSIX.1-1990 запрещает установку действия для сигнала SIGCHLD в SIG_IGN. POSIX.1-2001 допускает такую возможность, поэтому игнорирование SIGCHLD можно использовать для недопущения создания зомби (см. wait(2)). Тем не менее, поведение BSD и System V по игнорированию SIGCHLD различается, поэтому есть только один переносимый способ убедиться, что завершившийся потомок не стал зомби — поймать сигнал SIGCHLD и выполнить wait(2) или подобный вызов.

В POSIX.1-1990 указан только SA_NOCLDSTOP. В POSIX.1-2001 добавлены SA_NOCLDWAIT, SA_RESETHAND, SA_NODEFER и SA_SIGINFO. Использование в приложениях последних значений в sa_flags может оказаться менее переносимо на старые реализации UNIX.

Флаг SA_RESETHAND совместим с одноимённым флагом из SVr4.

Флаг SA_NODEFER совместим с одноименным флагом SVr4 в ядре версии 1.3.9 и более поздних. В старых выпусках ядра Linux позволяли принимать и обрабатывать любые сигналы, а не только те, обработка которых уже задана (на деле это приводит к игнорированию установок sa_mask).

Для получения адреса текущего обработчика сигнала можно использовать вызов sigaction(), указав NULL в качестве значения второго аргумента. Этот вызов можно также использовать для проверки доступности этого типа сигнала в конкретной системе, вызвав его с вторым и третьим аргументами, равными NULL.

Невозможно заблокировать сигналы SIGKILL или SIGSTOP (указав их в sa_mask). Попытки это сделать будут просто игнорироваться.

Подробная информация о работе с наборами сигналов есть на странице sigsetops(3).

Список функций безопасных асинхронных сигналов, которые можно не опасаясь вызывать из обработчика сигналов, смотрите в signal(7).

Недокументированное

До появления SA_SIGINFO существовала возможность получить дополнительную информацию, используя sa_handler со вторым параметром типа struct sigcontext. См. соответствующий исходный код ядра. В настоящее время этот механизм устарел.

ДЕФЕКТЫ

В ядрах по версию 2.6.13 включительно, указание SA_NODEFER в sa_flags предотвращает доставку сигнала не только из маскируемого при выполнении обработчика, но также сигналов, указанных в sa_mask. Этот дефект исправлен в ядре 2.6.14.

ПРИМЕР

Смотрите в mprotect(2).

СМОТРИТЕ ТАКЖЕ

kill(1), kill(2), killpg(2), pause(2), sigaltstack(2), signal(2), signalfd(2), sigpending(2), sigprocmask(2), sigsuspend(2), wait(2), raise(3), siginterrupt(3), sigqueue(3), sigsetops(3), sigvec(3), core(5), signal(7)

2012-04-26 Linux