sigaction

Autres langues

Langue: ja

Version: 2005-09-15 (fedora - 25/11/07)

Section: 2 (Appels système)

名前

sigaction - シグナルの動作の確認と変更

書式

 #include <signal.h>
 
 int sigaction(int signum, const struct sigaction *act,
               struct sigaction *oldact);
 

説明

sigaction() システムコールは、特定のシグナルを受信した際の プロセスの動作を変更するのに使用される。

signum には、 SIGKILLSIGSTOP 以外の有効なシグナルをどれでも指定できる。

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_handlersa_sigaction の両方を同時に割り当てることはできない。

sa_restorer 要素は廃止予定であり使用すべきではない。 POSIX には sa_restorer 要素に関する規定はない。

sa_handlersignum に対応する動作を指定するもので、 デフォルトの動作を行う SIG_DFL、 そのシグナルを無視する SIG_IGN、 シグナルハンドラ関数へのポインタが設定できる。 シグナルハンドラ関数の引き数は一つであり、シグナル番号が引き数として 渡される。

sa_flagsSA_SIGINFO が指定された場合、 (sa_handler ではなく) sa_sigaction により signum に対応するシグナルハンドル関数が指定される。 指定される関数は、最初の引き数としてシグナル番号を、 二番目の引き数として siginfo_t へのポインタを、三番目の引き数として (void * にキャストした) ucontext_t へのポインタを受けとる。

sa_mask は、シグナル・ハンドラ実行中に禁止 (block) するシグナルのマスクを表す。 さらに、 SA_NODEFER フラグが指定されていない場合は、ハンドラを起動するきっかけとなる シグナルにも sa_mask が適用される。

sa_flags はシグナル・ハンドラの動作を変更するためのフラグの集合を指定する。 sa_flags には、以下に示すフラグの (0個以上の) 論理和をとったものを指定する。

SA_NOCLDSTOP
signumSIGCHLD の場合、 子プロセスが停止したり (子プロセスが SIGSTOP, SIGTSTP, SIGTTIN, SIGTTOU を受けたとき) 再開したり (子プロセスが SIGCONT を受けたとき) したときに SIGCHLD の通知を受けない。
SA_NOCLDWAIT
(Linux 2.6 以降) signumSIGCHLD の場合、子プロセスが終了したときに 子プロセスをゾンビプロセスに変化させない (waitpid(2) も参照)。
SA_RESETHAND
シグナルハンドラが呼ばれる度に、シグナルの動作をデフォルトに戻す。 SA_ONESHOT はこのフラグと同じ意味だが、廃止されており、非標準である。
SA_ONSTACK
sigaltstack(2) で提供される別のシグナル・スタックでシグナルハンドラを呼び出す。 別のシグナル・スタックが利用可能でなければ、デフォルトのスタックが 使用される。
SA_RESTART
いくつかのシステムコールをシグナルの通知の前後で再開できるようにして、 BSD シグナル方式 (semantics) と互換性のある動作を提供する。
SA_NODEFER
それ自身のシグナル・ハンドラーの内部にいる時でも そのシグナルをマスクしないようにする。 SA_NOMASK はこのフラグと同じ意味だが、廃止されており、非標準である。
SA_SIGINFO
シグナルハンドラは一つではなく、三つの引き数を持つ。この場合は sa_handler のかわりに sa_sigaction を設定しなければならない (sa_sigaction フィールドは Linux 2.1.86 で追加された)。

sa_sigaction のパラメータ siginfo_t は以下の要素を持つ構造体である:

 siginfo_t {
     int      si_signo;    /* Signal number */
     int      si_errno;    /* An errno value */
     int      si_code;     /* Signal code */
     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 */
     sigval_t si_value;    /* Signal value */
     int      si_int;      /* POSIX.1b signal */
     void    *si_ptr;      /* POSIX.1b signal */
     void    *si_addr;     /* Memory location which caused fault */
     int      si_band;     /* Band event */
     int      si_fd;       /* File descriptor */
 }
 

si_signo, si_errno, si_code は全てのシグナルに対して定義されている (si_signo は Linux では使用されない)。 構造体の残りの部分は、共用体 (union) になっているかもしれない。 その場合は該当するシグナルにおいて意味のあるフィールドのみを読み込む ことができる。

*
POSIX.1b シグナルと SIGCHLDsi_pidsi_uid を設定する。 .IP* SIGCHLD はさらに si_status, si_utime, si_stime も設定する。
*
si_intsi_ptr は POSIX.1b シグナルの送信者によって指定される。 詳細は sigqueue(2) を参照のこと。
*
SIGILL, SIGFPE, SIGSEGV, SIGBUSsi_addr にエラーが発生したアドレスを設定する。 SIGPOLL は si_bandsi_fd を設定する。

si_code は、そのシグナルが送信された理由を示す。これは値でありビットマスクではない。 以下の表にはどのシグナルの場合でも使用できる値を記載している:

si_code
Value Signal origin
SI_USER kill(2) or raise(3)
SI_KERNEL The kernel
SI_QUEUE sigqueue(2)
SI_TIMER POSIX timer expired
SI_MESGQ POSIX message queue state changed (since Linux 2.6.6)
SI_ASYNCIO AIO completed
SI_SIGIO queued SIGIO
SI_TKILL tkill(2) or tgkill(2) (since Linux 2.4.19)
SIGILL
ILL_ILLOPC illegal opcode
ILL_ILLOPN illegal operand
ILL_ILLADR illegal addressing mode
ILL_ILLTRP illegal trap
ILL_PRVOPC privileged opcode
ILL_PRVREG privileged register
ILL_COPROC coprocessor error
ILL_BADSTK internal stack error
SIGFPE
FPE_INTDIV integer divide by zero
FPE_INTOVF integer overflow
FPE_FLTDIV floating point divide by zero
FPE_FLTOVF floating point overflow
FPE_FLTUND floating point underflow
FPE_FLTRES floating point inexact result
FPE_FLTINV floating point invalid operation
FPE_FLTSUB subscript out of range
SIGSEGV
SEGV_MAPERR address not mapped to object
SEGV_ACCERR invalid permissions for mapped object
SIGBUS
BUS_ADRALN invalid address alignment
BUS_ADRERR non-existent physical address
BUS_OBJERR object specific hardware error
SIGTRAP
TRAP_BRKPT process breakpoint
TRAP_TRACE process trace trap
SIGCHLD
CLD_EXITED child has exited
CLD_KILLED child was killed
CLD_DUMPED child terminated abnormally
CLD_TRAPPED traced child has trapped
CLD_STOPPED child has stopped
CLD_CONTINUED stopped child has continued (since Linux 2.6.9)
SIGPOLL
POLL_IN data input available
POLL_OUT output buffers available
POLL_MSG input message available
POLL_ERR i/o error
POLL_PRI high priority input available
POLL_HUP device disconnected

返り値

sigaction() は成功すれば 0 を返し、エラーならば -1 を返す。

エラー

EFAULT
actoldact が指しているメモリが正しいプロセスのアドレス空間にない。
EINVAL
無効なシグナルが指定された。補足 (catch) したり無視したりできない シグナルである SIGKILLSIGSTOP に対する動作を変更しようとした場合にも発生する。

準拠

POSIX.1-2001, SVr4.

注意

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 と SystemV では SIGCHLD を無視した際の動作が異なっている。 そのため、完全に移植性がある方法で、終了した子プロセスがゾンビにならないこと を保証するには、 SIGCHLD シグナルを補足し、 wait(2) などを実行するしかない。

POSIX.1-1990 の仕様では SA_NOCLDSTOP のみが定義されている。 POSIX.1-2001 では SA_NOCLDWAIT, SA_RESETHAND, SA_NODEFER, SA_SIGINFO が追加された。 Unix の古い実装で動かすアプリケーションで、 他の sa_flags フラグを使用すると移植性が下がる。

SA_SIGINFO フラグは Linux 2.2 からサポートされるようになった。

SA_RESETHAND フラグは SVr4 の同じ名前のフラグと互換性がある。

SA_NODEFER フラグは 1.3.9 以降のカーネルでは同じ名前の SVr4 のフラグと互換性がある。 ぞれ以前の Linux カーネルの実装では、このフラグを設定しているシグナル だけでなく、どのシグナルでも受けることを許していた (実際には sa_mask の設定により無効にできる)。

sigaction() の二番目の引き数に NULL を指定して呼び出すと、現在のシグナルハンドラを確認する ことができる。また、二番目と三番目の引き数を NULL にて呼び出すことで、 指定されたシグナルが現在のマシンで使えるかどうかチェックできる。

SIGKILLSIGSTOP を (sa_mask に指定して) 禁止することはできない。 禁止しようとしても黙って無視される。

シグナル集合の操作に関する詳細は sigsetops(3) を参照すること。

シグナルハンドラ内から安全に呼び出すことができる、 async-signal-safe functions (非同期シングルで安全な関数) の リストについては signal(7) を参照。

非公式

SA_SIGINFO が導入される前は、 struct sigcontext 型の二番目の引き数と一緒に sa_handler を使用することで、 いくつかの追加の情報を入手することができた。 詳細についてはカーネルソースの関連部分を見てほしい。 現在はこの使用法は廃止されている。

バグ

2.6.13 以前のカーネルでは、 sa_flagsSA_NODEFER を指定した場合、 ハンドラが実行中に配送されたシグナル自身がマスクされなくなるだけでなく、 sa_mask に指定されたシグナルもマスクされなくなる。 このバグは、カーネル 2.6.14 で修正された。

mprotect(2) 参照。

関連項目

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