Главная » 2017 » Ноябрь » 24 » man 2 sigaction
05:26
man 2 sigaction

SEO sprint - Всё для максимальной раскрутки!





ИМЯ


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



ОБЗОР


#include <signal.h>

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

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

sigaction(): _POSIX_C_SOURCE

siginfo_t: _POSIX_C_SOURCE >= 199309L



ОПИСАНИЕ


Системный вызов 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 не
определёно). Предназначение этого поля немного описано в sigreturn(2).

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

Если в sa_flags указан SA_SIGINFO, то sa_sigaction (вместо sa_handler) задаёт функцию
обработки сигнала signum. Эта функция имеет три параметра, которые описаны ниже.

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

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

состояние зомби при завершении. Смотрите также waitpid(2). Этот флаг имеет
значение только когда установлен обработчик SIGCHLD или когда обработчик сигнала
установлен в SIG_DFL.

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

SA_NODEFER
Не препятствовать получению сигнала при его обработке обработчиком сигнала. Этот
флаг имеет значение только когда установлен обработчик. Флаг SA_NOMASK является
устаревшим синонимом данного флага.

SA_ONSTACK
Вызывать обработчик сигнала в дополнительном стеке сигналов, предоставленном
sigaltstack(2). Если дополнительный стек недоступен, то будет использован стек по
умолчанию. Этот флаг имеет значение только когда установлен обработчик.

SA_RESETHAND
Восстановить поведение сигнала в значение по умолчанию после входа в обработчик
сигнала. Этот флаг имеет значение только когда установлен обработчик. Флаг
SA_ONESHOT является устаревшим синонимом данного флага.

SA_RESTART
Обеспечивать поведение совместимое с семантикой сигналов BSD, позволяя некоторым
системным вызовам перезапускаться в то время, как идет обработка сигналов. Этот
флаг имеет значение только когда установлен обработчик. О перезапуске системных
вызовов смотрите в signal(7).

SA_RESTORER
Не предназначен для приложений. Данный флаг используется в библиотеках C для
указания на то, что поле sa_restorer содержит адрес «прыжковым мостиком в сигнал"
(signal trampoline). Подробней смотрите в sigreturn(2).

SA_SIGINFO (начиная с Linux 2.2)
Обработчик сигнала требует трёх аргументов, а не одного. В этом случае надо
использовать параметр sa_sigaction вместо sa_handler. Этот флаг имеет значение
только когда установлен обработчик.

Аргумент siginfo_t обработчика SA_SIGINFO.
Если в act.sa_flags указан флаг SA_SIGINFO, то адрес обработчика сигнала передаётся в поле
act.sa_sigaction. Этот обработчик имеет три аргумента:

void
handler(int sig, siginfo_t *info, void *ucontext)
{
...
}

Три параметра:

sig Номер сигнала, который привёл к вызову обработчика.

info Указатель на siginfo_t — структуру, содержащую дополнительную информацию о сигнале,
описана далее.

siginfo_t {
int si_signo; /* Номер сигнала */
int si_errno; /* Значение errno */
int si_code; /* Код сигнала */
int si_trapno; /* Номер ловушки, которую вызвал
аппаратный сигнал
(не используется на большинстве
архитектур) */
pid_t si_pid; /* ID процесса, пославшего сигнал */
uid_t si_uid; /* ID реального пользователя процесса,
пославшего сигнал */
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; /* ID таймера; таймеры POSIX.1b */
void *si_addr; /* Адрес памяти, приводящий к ошибке */
long si_band; /* Внутреннее событие (был int в
glibc 2.3.2 и более ранних) */
int si_fd; /* Файловый дескриптор */
short si_addr_lsb; /* Наименее значимый бит адреса
(начиная с Linux 2.6.32) */
void *si_lower; /* Нижняя граница при нарушении адреса
(начиная с Linux 3.19) */
void *si_upper; /* Верхняя граница при нарушении адреса
(начиная с Linux 3.19) */
int si_pkey; /* Ключа защиты в PTE, который привёл
к ошибке (начиная с Linux 4.6) */
void *si_call_addr; /* Адрес инструкции системного вызова
(начиная с Linux 3.5) */
int si_syscall; /* Количество попыток системного вызова
(начиная с Linux 3.5) */
unsigned int si_arch; /* Архитектура пытавшегося системного вызова
(начиная с Linux 3.5) */
}

Поля 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, предоставляемым
использованное на ожидание потомков (в отличие от getrusage(2) и times(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)). Когда доставляется SIGTRAP в ответ на
событие ptrace(2) (PTRACE_EVENT_foo), то si_addr не заполняется, но заполняются si_pid и
si_uid соответствующими ID процесса и пользователя, ответственного за получение трапа. В
случае seccomp(2), трассируемый будет показан как получающий событие. BUS_MCERR_* и
si_addr_lsb являются расширениями Linux.

Для отдельного варианта SEGV_BNDERR из SIGSEGV заполняются si_lower и si_upper.

Для отдельного варианта SEGV_PKUERR из SIGSEGV заполняется si_pkey.

* Для SIGIO/SIGPOLL (синонимы в Linux) заполняются si_band и si_fd. Событие si_band
представляет собой битовую маску, содержащую те же значения, которые заполняются в поле
revents вызовом poll(2). Поле si_fd содержит файловый дескриптор, для которого произошло
событие ввода-вывода; дополнительную информацию смотрите в описании F_SETSIG на странице
fcntl(2).

* Для SIGSYS, генерируемого (начиная с Linux 3.5), когда фильтр seccomp возвращает
SECCOMP_RET_TRAP, заполняются si_call_addr, si_syscall, si_arch, si_errno и другие поля,
как описывается в seccomp(2).

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

(SIGTRAP | PTRACE_EVENT_foo << 8).

Не события не ptrace(2) значения, которые могут появиться в si_code, описаны в конце этого
раздела. Начиная с glibc 2.20, определения большинства этих символов доступны из <signal.h>
при определении макросов тестирования свойств (до включения какого-либо заголовочного файла)
следующим образом:

* _XOPEN_SOURCE со значением 500 или больше;

* _XOPEN_SOURCE и _XOPEN_SOURCE_EXTENDED; или

* _POSIX_C_SOURCE со значением 200809L или больше.

Определения символов констант TRAP_* предоставляются только в первых двух случаях. До glibc
2.20 для получения этих символов макросы тестирования свойств были не нужны.

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

SI_USER
kill(2).

SI_MESGQ (начиная с Linux 2.6.6)
изменилось состояние очереди сообщений POSIX; см. mq_notify(3).

SI_ASYNCIO
AIO завершён.

SI_SIGIO
Queued SIGIO (только в ядрах до Linux 2.2; начиная с Linux 2.4 SIGIO/SIGPOLL
заполняют si_code как описано выше).

SI_TKILL (начиная с Linux 2.4.19)
tkill(2) или tgkill(2).

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

ILL_ILLOPC
Некорректный код инструкции.

ILL_ILLOPN
Некорректный операнд.

ILL_ILLADR
Некорректный режим адресации.

ILL_ILLTRP
Некорректная ловушка.

ILL_PRVOPC
Привилегированный код инструкции.

ILL_PRVREG
Привилегированный регистр.

ILL_COPROC
Ошибка сопроцессора.

ILL_BADSTK
Внутренняя ошибка стека.

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

FPE_INTDIV
Деление на ноль при работе с целыми числами.

FPE_INTOVF
Переполнение при работе с целыми числами.

FPE_FLTDIV
Деление на ноль при работе с числами с плавающей запятой.

FPE_FLTOVF
Переполнение при работе с числами с плавающей запятой.

FPE_FLTUND
Нехватка значения при работе с числами с плавающей запятой.

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

SEGV_MAPERR
Адрес не соответствует объекту.

SEGV_ACCERR
Некорректные права на отображённый объект.

SEGV_BNDERR (начиная с Linux 3.19)
Ошибка проверки границ адреса.

SEGV_PKUERR (начиная с Linux 4.6)
Доступ запрещён битами защиты памяти. Смотрите pkeys(7). Ключ защиты, применяемый
при таком доступе, доступен в si_pkey.

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

BUS_ADRALN
Некорректное выравнивание адреса.

BUS_ADRERR
Несуществующий физический адрес.

BUS_OBJERR
Аппаратная ошибка, специфичная для объекта.

BUS_MCEERR_AR (начиная с Linux 2.6.32)
машинной проверкой устранена аппаратная ошибка памяти; требуется действие

BUS_MCEERR_AO (начиная с Linux 2.6.32)
в процессе обнаружена аппаратная ошибка памяти, но не устранена; действие не
обязательно

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

TRAP_BRKPT
Точка останова процесса.

TRAP_TRACE
Ловушка отладки процесса.

TRAP_BRANCH (начиная с Linux 2.4, только для IA64))
Процесс пойман в ветвь ловушки.

TRAP_HWBKPT (начиная с Linux 2.4, только для IA64))
Аппаратная точка прерывания/слежения.

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

CLD_EXITED
Дочерний процесс завершил работу.

CLD_KILLED
Работа дочернего процесса была прервана.

CLD_DUMPED
Дочерний процесс завершился некорректно.

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

POLL_IN
Есть входные данные.

POLL_OUT
Освободились выходные буферы.

POLL_MSG
Есть входное сообщение.

POLL_ERR
Ошибка ввода-вывода.

POLL_PRI
Есть входные данные высокого приоритета.

POLL_HUP
Устройство отключено.

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

SYS_SECCOMP (начиная с Linux 3.5)
Возникает по правилу фильтрации seccomp(2).



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


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



ОШИБКИ


EFAULT act или oldact указывают на память, которая не является частью адресного пространства
процесса.

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



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


POSIX.1-2001, POSIX.1-2008, 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 различается, поэтому есть только один переносимый способ

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

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

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

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

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

Отличия между библиотекой C и ядром
Обёрточная функция glibc для sigaction() выдаёт ошибку (EINVAL) при попытках изменить
обработчики двух сигналов реального времени, которые используются внутри реализации NPTL.
Подробности смотрите в nptl(7).

На архитектурах, где переход от сигнала (signal trampoline) располагается в библиотеке C,
обёрточная функция glibc для sigaction() помещает адрес кода перехода в поле act.sa_restorer
и изменяет флаг SA_RESTORER в поле act.sa_flags. Смотрите sigreturn(2).

Первоначально, системный вызов Linux назывался sigaction(). Однако, с добавлением сигналов
реального времени в Linux 2.2, 32-битный аргумент sigset_t неизменяемого размера,
поддерживаемый этим системным вызовом, не мог больше использоваться. В результате был
добавлен новый системный вызов rt_sigaction() с увеличенным типом sigset_t. У нового
системного вызова появился четвёртый аргумент, size_t sigsetsize, в котором указывается
размер (в байтах) наборов сигналов act.sa_mask и oldact.sa_mask. В настоящее время значение
этого аргумента должно быть равно sizeof(sigset_t) (иначе возникает ошибка EINVAL).
Обёрточная функция glibc sigaction() скрывает это и вызывает rt_sigaction(), если он есть в
ядре.

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



ДЕФЕКТЫ


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



ПРИМЕР


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



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


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



Категория: (2) Системные вызовы ядра (функции языка Си) | Просмотров: 393 | Добавил: Администратор | Рейтинг: 0.0/0
Всего комментариев: 0
avatar