SIGACTION(2) | Linux Programmer's Manual | SIGACTION(2) |
sigaction, rt_sigaction - シグナルの動作の確認と変更
#include <signal.h>
int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);
sigaction(): _POSIX_C_SOURCE
siginfo_t: _POSIX_C_SOURCE >= 199309L
sigaction() システムコールは、特定のシグナルを受信した際の プロセスの動作を変更するのに使用される (シグナルの概要については signal(7) を参照)。
signum には、 SIGKILL と SIGSTOP 以外の有効なシグナルをどれでも指定できる。
act が NULL 以外であれば、シグナル signum の新しい動作 (action) として 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 is be one of the following:
If SA_SIGINFO is specified in sa_flags, then sa_sigaction (instead of sa_handler) specifies the signal-handling function for signum. This function receives three arguments, as described below.
sa_mask は、シグナルハンドラー実行中に禁止 (block) すべきシグナルのマスクを指定する (ハンドラー実行中のシグナルの禁止は、シグナルハンドラーが起動されたスレッド のシグナルのマスクに追加することで行われる)。 さらに、 SA_NODEFER フラグが指定されていない場合は、ハンドラーを起動するきっかけとなる シグナルにも sa_mask が適用される。
sa_flags はシグナルハンドラーの動作を変更するためのフラグの集合を指定する。 sa_flags には、以下に示すフラグの (0 個以上の) 論理和をとったものを指定する。
When the SA_SIGINFO flag is specified in act.sa_flags, the signal handler address is passed via the act.sa_sigaction field. This handler takes three arguments, as follows:
void handler(int sig, siginfo_t *info, void *ucontext) { ... }
These three arguments are as follows
The siginfo_t data type is a structure with the following fields:
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 では一般的には使用されない)。 構造体の残りの部分は、共用体 (union) になっているかもしれない。 その場合は該当するシグナルにおいて意味のあるフィールドのみを読み込む ことができる。
The si_code field inside the siginfo_t argument that is passed to a SA_SIGINFO signal handler is a value (not a bit mask) indicating why this signal was sent. For a ptrace(2) event, si_code will contain SIGTRAP and have the ptrace event in the high byte:
(SIGTRAP | PTRACE_EVENT_foo << 8).
For a non-ptrace(2) event, the values that can appear in si_code are described in the remainder of this section. Since glibc 2.20, the definitions of most of these symbols are obtained from <signal.h> by defining feature test macros (before including any header file) as follows:
For the TRAP_* constants, the symbol definitions are provided only in the first two cases. Before glibc 2.20, no feature test macros were required to obtain these symbols.
通常のシグナルの場合には、 以下のリストに示す値がどのシグナルの場合でも si_code に入りうる。シグナルが生成された理由も記載している。
SIGILL シグナルの場合、 si_code には以下の値が入る可能性がある:
SIGFPE シグナルの場合、 si_code には以下の値が入る可能性がある:
SIGSEGV シグナルの場合、 si_code には以下の値が入る可能性がある:
SIGBUS シグナルの場合、 si_code には以下の値が入る可能性がある:
SIGTRAP シグナルの場合、 si_code には以下の値が入る可能性がある:
SIGCHLD シグナルの場合、 si_code には以下の値が入る可能性がある:
SIGIO/SIGPOLL シグナルの場合、 si_code には以下の値が入る可能性がある:
SIGSYS シグナルの場合、 si_code には以下の値が入る可能性がある:
sigaction() 関数は成功すると 0 を返す。 エラーの場合、-1 を返し、 errno にエラーを示す値をセットする。
POSIX.1-2001, POSIX.1-2008, SVr4.
fork(2) 経由で作成された子プロセスは、親プロセスのシグナルの処理方法の コピーを継承する。 execve(2) の前後で、ハンドラーが設定されているシグナルの処理方法はデフォルトにリセットされ、 無視が設定されているシグナルの処理方法は変更されずそのままとなる。
POSIX では、 kill(2) や raise(3) で生成できないシグナル SIGFPE, SIGILL, SIGSEGV を無視 (ignore) した場合、その後の動作は未定義である。 ゼロによる整数割り算の結果は未定義となる。 アーキテクチャーによっては、このとき 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 が追加された。 UNIX の古い実装で動かすアプリケーションで、 他の sa_flags フラグを使用すると移植性が下がる。
SA_RESETHAND フラグは SVr4 の同じ名前のフラグと互換性がある。
SA_NODEFER フラグは 1.3.9 以降のカーネルでは同じ名前の SVr4 のフラグと互換性がある。 ぞれ以前の Linux カーネルの実装では、このフラグを設定しているシグナル だけでなく、どのシグナルでも受けることを許していた (実際には sa_mask の設定により無効にできる)。
sigaction() の二番目の引数に NULL を指定して呼び出すと、現在のシグナルハンドラーを確認する ことができる。また、二番目と三番目の引数を NULL にて呼び出すことで、 指定されたシグナルが現在のマシンで使えるかどうかチェックできる。
SIGKILL や SIGSTOP を (sa_mask に指定して) 禁止することはできない。 禁止しようとしても黙って無視される。
シグナル集合の操作に関する詳細は sigsetops(3) を参照のこと。
シグナルハンドラー内から安全に呼び出すことができる、 async-signal-safe functions (非同期シグナルで安全な関数) の リストについては signal-safety(7) を参照。
The glibc wrapper function for sigaction() gives an error (EINVAL) on attempts to change the disposition of the two real-time signals used internally by the NPTL threading implementation. See nptl(7) for details.
On architectures where the signal trampoline resides in the C library, the glibc wrapper function for sigaction() places the address of the trampoline code in the act.sa_restorer field and sets the SA_RESTORER flag in the act.sa_flags field. See sigreturn(2).
The original Linux system call was named sigaction(). However, with the addition of real-time signals in Linux 2.2, the fixed-size, 32-bit sigset_t type supported by that system call was no longer fit for purpose. Consequently, a new system call, rt_sigaction(), was added to support an enlarged sigset_t type. The new system call takes a fourth argument, size_t sigsetsize, which specifies the size in bytes of the signal sets in act.sa_mask and oldact.sa_mask. This argument is currently required to have the value sizeof(sigset_t) (or the error EINVAL results). The glibc sigaction() wrapper function hides these details from us, transparently calling rt_sigaction() when the kernel provides it.
Before the introduction of SA_SIGINFO, it was also possible to get some additional information about the signal. This was done by providing an sa_handler signal handler with a second argument of type struct sigcontext, which is the same structure as the one that is passed in the uc_mcontext field of the ucontext structure that is passed (via a pointer) in the third argument of the sa_sigaction handler. See the relevant Linux kernel sources for details. This use is obsolete now.
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.
2.6.13 以前のカーネルでは、 sa_flags に SA_NODEFER を指定した場合、 ハンドラーが実行中に配送されたシグナル自身がマスクされなくなるだけでなく、 sa_mask に指定されたシグナルもマスクされなくなる。 このバグは、カーネル 2.6.14 で修正された。
mprotect(2) 参照。
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)
この man ページは Linux man-pages プロジェクトのリリース 5.10 の一部である。プロジェクトの説明とバグ報告に関する情報は https://www.kernel.org/doc/man-pages/ に書かれている。
2020-12-21 | Linux |