ИМЯ
sigaction, rt_sigaction - получает и изменяет обработчик сигналаLIBRARY
Standard C library ( libc, -lc)СИНТАКСИС
#include <signal.h>
int sigaction(int signum, const struct sigaction *_Nullable restrict act, struct sigaction *_Nullable restrict oldact);
Требования
макроса
тестирования
свойств
для glibc (см.
feature_test_macros(7)):
sigaction():
_POSIX_C_SOURCEsiginfo_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 specifies the action to be associated with signum and can be one of the following:
- •
- SIG_DFL for the default action.
- •
- SIG_IGN to ignore this signal.
- •
- A pointer to a signal handling function. This function receives the signal number as its only argument.
- SA_NOCLDSTOP
- Если значение signum равно SIGCHLD, то уведомление об остановке дочернего процесса (т.е., в тех случаях, когда дочерний процесс получает сигнал SIGSTOP, SIGTSTP, SIGTTIN или SIGTTOU) или возобновлении работы (т.е., когда дочерний процесс получает SIGCONT) не будет получено (см. wait(2)). Этот флаг имеет значение только когда установлен обработчик SIGCHLD.
- SA_NOCLDWAIT (начиная с Linux 2.6)
- Если значение signum равно SIGCHLD, то дочерние процессы не будут переводиться в состояние зомби при завершении. Смотрите также waitpid(2). Этот флаг имеет значение только когда установлен обработчик SIGCHLD или когда обработчик сигнала установлен в SIG_DFL.
- Если флаг SA_NOCLDWAIT не задан при установке обработчика SIGCHLD, то по POSIX.1 остаётся неопределённым, будет ли генерироваться сигнал SIGCHLD при завершении дочернего процесса. В Linux сигнал SIGCHLD в этом случае генерируется; в некоторых других реализациях это не делается.
- SA_NODEFER
- Do not add the signal to the thread's signal mask while the handler is executing, unless the signal is specified in act.sa_mask. Consequently, a further instance of the signal may be delivered to the thread while it is executing the handler. This flag is meaningful only when establishing a signal handler.
- SA_NOMASK is an obsolete, nonstandard synonym for this flag.
- SA_ONSTACK
- Вызывать обработчик сигнала в дополнительном стеке сигналов, предоставленном sigaltstack(2). Если дополнительный стек недоступен, то будет использован стек по умолчанию. Этот флаг имеет значение только когда установлен обработчик.
- SA_RESETHAND
- Restore the signal action to the default upon entry to the signal handler. This flag is meaningful only when establishing a signal handler.
- SA_ONESHOT is an obsolete, nonstandard synonym for this flag.
- SA_RESTART
- Обеспечивать поведение совместимое с семантикой сигналов BSD, позволяя некоторым системным вызовам перезапускаться в то время, как идет обработка сигналов. Этот флаг имеет значение только когда установлен обработчик. О перезапуске системных вызовов смотрите в signal(7).
- SA_RESTORER
- Не предназначен для приложений. Данный флаг используется в библиотеках C для указания на то, что поле sa_restorer содержит адрес «прыжковым мостиком в сигнал" (signal trampoline). Подробней смотрите в sigreturn(2).
- SA_SIGINFO (начиная с Linux 2.2)
- Обработчик сигнала требует трёх аргументов, а не одного. В этом случае надо использовать параметр sa_sigaction вместо sa_handler. Этот флаг имеет значение только когда установлен обработчик.
- SA_UNSUPPORTED (начиная с Linux 5.11)
- Used to dynamically probe for flag bit support.
- If an attempt to register a handler succeeds with this flag set in act->sa_flags alongside other flags that are potentially unsupported by the kernel, and an immediately subsequent sigaction() call specifying the same signal number and with a non-NULL oldact argument yields SA_UNSUPPORTED clear in oldact->sa_flags, then oldact->sa_flags may be used as a bitmask describing which of the potentially unsupported flags are, in fact, supported. See the section "Dynamically probing for flag bit support" below for more details.
- SA_EXPOSE_TAGBITS (начиная с Linux 5.11)
- Normally, when delivering a signal, an architecture-specific set of tag bits are cleared from the si_addr field of siginfo_t. If this flag is set, an architecture-specific subset of the tag bits will be preserved in si_addr.
- Programs that need to be compatible with Linux versions older than 5.11 must use SA_UNSUPPORTED to probe for support.
Аргумент 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 — структуру, содержащую дополнительную информацию о сигнале, описана далее.
- ucontext
- This is a pointer to a ucontext_t structure, cast to void *. The structure pointed to by this field contains signal context information that was saved on the user-space stack by the kernel; for details, see sigreturn(2). Further information about the ucontext_t structure can be found in getcontext(3) and signal(7). Commonly, the handler function doesn't make any use of the third argument.
siginfo_t { int si_signo; /* Signal number */ int si_errno; /* An errno value */ int si_code; /* Signal code */ int si_trapno; /* Trap number that caused hardware-generated signal (unused on most architectures) */ pid_t si_pid; /* Sending process ID */ uid_t si_uid; /* Real user ID of sending process */ int si_status; /* Exit value or signal */ clock_t si_utime; /* User time consumed */ clock_t si_stime; /* System time consumed */ union sigval si_value; /* Signal value */ int si_int; /* POSIX.1b signal */ void *si_ptr; /* POSIX.1b signal */ int si_overrun; /* Timer overrun count; POSIX.1b timers */ int si_timerid; /* Timer ID; POSIX.1b timers */ void *si_addr; /* Memory location which caused fault */ long si_band; /* Band event (was int in glibc 2.3.2 and earlier) */ int si_fd; /* File descriptor */ short si_addr_lsb; /* Least significant bit of address (since Linux 2.6.32) */ void *si_lower; /* Lower bound when address violation occurred (since Linux 3.19) */ void *si_upper; /* Upper bound when address violation occurred (since Linux 3.19) */ int si_pkey; /* Protection key on PTE that caused fault (since Linux 4.6) */ void *si_call_addr; /* Address of system call instruction (since Linux 3.5) */ int si_syscall; /* Number of attempted system call (since Linux 3.5) */ unsigned int si_arch; /* Architecture of attempted system call (since 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, предоставляемым mq_notify(3); si_pid — значением идентификатора процесса, отправившего сообщение; si_uid — значением реального идентификатора пользователя, отправившего сообщение.
- •
- SIGCHLD fills in si_pid, si_uid, si_status, si_utime, and si_stime, providing information about the child. The si_pid field is the process ID of the child; si_uid is the child's real user ID. The si_status field contains the exit status of the child (if si_code is CLD_EXITED), or the signal number that caused the process to change state. The si_utime and si_stime contain the user and system CPU time used by the child process; these fields do not include the times used by waited-for children (unlike getrusage(2) and times(2)). Up to Linux 2.6, and since Linux 2.6.27, these fields report CPU time in units of sysconf(_SC_CLK_TCK). In Linux 2.6 kernels before Linux 2.6.27, a bug meant that these fields reported time in units of the (configurable) system jiffy (see 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 или больше.
- SI_USER
- kill(2).
- SI_KERNEL
- посылается ядром
- SI_QUEUE
- sigqueue(3).
- SI_TIMER
- таймер POSIX истёк.
- SI_MESGQ (начиная с Linux 2.6.6)
- изменилось состояние очереди сообщений POSIX; см. mq_notify(3).
- SI_ASYNCIO
- AIO завершён.
- SI_SIGIO
- Queued SIGIO (only up to Linux 2.2; from Linux 2.4 onward SIGIO/SIGPOLL fills in si_code as described below).
- ILL_ILLOPC
- Некорректный код инструкции.
- ILL_ILLOPN
- Некорректный операнд.
- ILL_ILLADR
- Некорректный режим адресации.
- ILL_ILLTRP
- Некорректная ловушка.
- ILL_PRVOPC
- Привилегированный код инструкции.
- ILL_PRVREG
- Привилегированный регистр.
- ILL_COPROC
- Ошибка сопроцессора.
- ILL_BADSTK
- Внутренняя ошибка стека.
- FPE_INTDIV
- Деление на ноль при работе с целыми числами.
- FPE_INTOVF
- Переполнение при работе с целыми числами.
- FPE_FLTDIV
- Деление на ноль при работе с числами с плавающей запятой.
- FPE_FLTOVF
- Переполнение при работе с числами с плавающей запятой.
- FPE_FLTUND
- Нехватка значения при работе с числами с плавающей запятой.
- FPE_FLTRES
- Неточный результат при работе с числами с плавающей запятой.
- FPE_FLTINV
- Неправильная операция при работе с числами с плавающей запятой.
- FPE_FLTSUB
- Индекс вне разрешенных пределов при работе с числами с плавающей запятой.
- SEGV_MAPERR
- Адрес не соответствует объекту.
- SEGV_ACCERR
- Некорректные права на отображённый объект.
- SEGV_BNDERR (начиная с Linux 3.19)
- Ошибка проверки границ адреса.
- SEGV_PKUERR (начиная с Linux 4.6)
- Доступ запрещён битами защиты памяти. Смотрите pkeys(7). Ключ защиты, применяемый при таком доступе, доступен в si_pkey.
- BUS_ADRALN
- Некорректное выравнивание адреса.
- BUS_ADRERR
- Несуществующий физический адрес.
- BUS_OBJERR
- Аппаратная ошибка, специфичная для объекта.
- BUS_MCEERR_AR (начиная с Linux 2.6.32)
- машинной проверкой устранена аппаратная ошибка памяти; требуется действие
- BUS_MCEERR_AO (начиная с Linux 2.6.32)
- в процессе обнаружена аппаратная ошибка памяти, но не устранена; действие не обязательно
- TRAP_BRKPT
- Точка останова процесса.
- TRAP_TRACE
- Ловушка отладки процесса.
- TRAP_BRANCH (начиная с Linux 2.4, только для IA64)
- Процесс пойман в ветвь ловушки.
- TRAP_HWBKPT (начиная с Linux 2.4, только для IA64)
- Аппаратная точка прерывания/слежения.
- CLD_EXITED
- Дочерний процесс завершил работу.
- CLD_KILLED
- Работа дочернего процесса была прервана.
- CLD_DUMPED
- Дочерний процесс завершился некорректно.
- CLD_TRAPPED
- Сработала ловушка в отлаживаемом дочернем процессе.
- CLD_STOPPED
- Дочерний процесс остановлен.
- CLD_CONTINUED (начиная с Linux 2.6.9)
- Остановленный дочерний процесс продолжил работу.
- POLL_IN
- Есть входные данные.
- POLL_OUT
- Освободились выходные буферы.
- POLL_MSG
- Есть входное сообщение.
- POLL_ERR
- Ошибка ввода-вывода.
- POLL_PRI
- Есть входные данные высокого приоритета.
- POLL_HUP
- Устройство отключено.
- SYS_SECCOMP (начиная с Linux 3.5)
- Возникает по правилу фильтрации seccomp(2).
Dynamically probing for flag bit support
The sigaction() call on Linux accepts unknown bits set in act->sa_flags without error. The behavior of the kernel starting with Linux 5.11 is that a second sigaction() will clear unknown bits from oldact->sa_flags. However, historically, a second sigaction() call would typically leave those bits set in oldact->sa_flags. This means that support for new flags cannot be detected simply by testing for a flag in sa_flags, and a program must test that SA_UNSUPPORTED has been cleared before relying on the contents of sa_flags. Since the behavior of the signal handler cannot be guaranteed unless the check passes, it is wise to either block the affected signal while registering the handler and performing the check in this case, or where this is not possible, for example if the signal is synchronous, to issue the second sigaction() in the signal handler itself. In kernels that do not support a specific flag, the kernel's behavior is as if the flag was not set, even if the flag was set in act->sa_flags. The flags SA_NOCLDSTOP, SA_NOCLDWAIT, SA_SIGINFO, SA_ONSTACK, SA_RESTART, SA_NODEFER, SA_RESETHAND, and, if defined by the architecture, SA_RESTORER may not be reliably probed for using this mechanism, because they were introduced before Linux 5.11. However, in general, programs may assume that these flags are supported, since they have all been supported since Linux 2.6, which was released in the year 2003. See EXAMPLES below for a demonstration of the use of SA_UNSUPPORTED.ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ
При успешном выполнении 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 различается, поэтому есть только один переносимый способ убедиться, что завершившийся потомок не стал зомби — поймать сигнал SIGCHLD и выполнить wait(2) или подобный вызов. В POSIX.1-1990 указан только SA_NOCLDSTOP. В POSIX.1-2001 добавлены SA_NOCLDSTOP, SA_NOCLDWAIT, SA_NODEFER, SA_ONSTACK, SA_RESETHAND, SA_RESTART и 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-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, который повторяет структуру, передаваемую в поле uc_mcontext структуры ucontext, которая передаётся (через указатель) в третьем аргументе обработчика sa_sigaction. Смотрите соответствующий исходный код ядра Linux. В настоящее время этот механизм устарел.ДЕФЕКТЫ
When delivering a signal with a SA_SIGINFO handler, the kernel does not always provide meaningful values for all of the fields of the siginfo_t that are relevant for that signal. Up to and including Linux 2.6.13, specifying SA_NODEFER in sa_flags prevents not only the delivered signal from being masked during execution of the handler, but also the signals specified in sa_mask. This bug was fixed in Linux 2.6.14.ПРИМЕРЫ
Смотрите в mprotect(2).Probing for flag support
The following example program exits with status EXIT_SUCCESS if SA_EXPOSE_TAGBITS is determined to be supported, and EXIT_FAILURE otherwise.#include <signal.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> void handler(int signo, siginfo_t *info, void *context) { struct sigaction oldact; if (sigaction(SIGSEGV, NULL, &oldact) == -1 || (oldact.sa_flags & SA_UNSUPPORTED) || !(oldact.sa_flags & SA_EXPOSE_TAGBITS)) { _exit(EXIT_FAILURE); } _exit(EXIT_SUCCESS); } int main(void) { struct sigaction act = { 0 }; act.sa_flags = SA_SIGINFO | SA_UNSUPPORTED | SA_EXPOSE_TAGBITS; act.sa_sigaction = &handler; if (sigaction(SIGSEGV, &act, NULL) == -1) { perror("sigaction"); exit(EXIT_FAILURE); } raise(SIGSEGV); }
СМ. ТАКЖЕ
kill(1), kill(2), pause(2), pidfd_send_signal(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)ПЕРЕВОД
Русский перевод этой страницы руководства был сделан Alexander Golubev <[email protected]>, Azamat Hackimov <[email protected]>, Hotellook, Nikita <[email protected]>, Spiros Georgaras <[email protected]>, Vladislav <[email protected]>, Yuri Kozlov <[email protected]> и Иван Павлов <[email protected]> Этот перевод является бесплатной документацией; прочитайте Стандартную общественную лицензию GNU версии 3 или более позднюю, чтобы узнать об условиях авторского права. Мы не несем НИКАКОЙ ОТВЕТСТВЕННОСТИ. Если вы обнаружите ошибки в переводе этой страницы руководства, пожалуйста, отправьте электронное письмо на [email protected]10 февраля 2023 г. | Linux man-pages 6.03 |