EN JA
SIGACTION(2)
SIGACTION(2) FreeBSD System Calls Manual SIGACTION(2)

名称

sigactionソフトウェアシグナル機能

ライブラリ

Standard C Library (libc, -lc)

書式

#include < signal.h>

struct  sigaction { 
        void    (*sa_handler)(int); 
        void    (*sa_sigaction)(int, siginfo_t *, void *); 
        int     sa_flags;               /* 下記のシグナルオプション参照 */ 
        sigset_t sa_mask;               /* 適用するシグナルマスク */ 
};


int
sigaction( int sig, const struct sigaction * restrict act, struct sigaction * restrict oact);

解説

システムは、プロセスに配信される 1 組のシグナルを定義しています。シグナルの配信は、ハードウェア割り込みの発生に似ています: シグナルは、通常、さらなる発生はブロックされ、現在のスレッドのコンテキストは、保存され、新しいものが、構築されます。プロセスは、シグナルが配信される handler (ハンドラ) を指定するか、またはシグナルが 無視 されることを指定します。また、プロセスは、デフォルトのアクションがシグナルが発生するとき、システムによって取られることを指定します。また、シグナルは、スレッドのために ブロック され、その場合に、 ブロックが解除 されるまで、そのスレッドに配信されません。配信で取られるアクションは、配信のときに決定されます。通常、シグナルハンドラは、スレッドの現在のスタックで実行します。これは、ハンドラ単位で、変更され、その結果、シグナルは、特別の シグナルスタック に取られます。

通常、シグナルルーチンは、 ブロック された、それらの呼び出しを引き起こしたシグナルで実行しますが、他のシグナルは、まだ起こります。グローバルな シグナルマスク は、スレッドへの配信から現在ブロックされているシグナルのセットを定義します。スレッドのためのシグナルマスクは、その親 (通常、空) のシグナルマスクから初期化されます。それは、 sigprocmask(2) または pthread_sigmask(3) 呼び出しか、またはシグナルがスレッドに配信されるとき、変更されます。

シグナル状態がプロセスまたはスレッドのために発生するとき、シグナルは、プロセスまたはスレッドのための保留中のシグナルのセットに追加されます。シグナルが、一般的にプロセス、または特定のスレッドに向けられるかどうかは、それが、どのように生成されるかに依存します。特定のスレッドに向けられたシグナルに関して、シグナルが、スレッドによって現在 グロック されていないなら、それは、スレッドに配信されます。プロセス向けられたシグナルに関して、シグナルが、すべてのスレッドによって、現在 グロック されていないなら、(その選択が、指定されていない) ブロックされていない 1 つのスレッドに配信されます。シグナルは、スレッドがオペレーティングシステムに入るときはいつでも (例えば、システムコール、ページフォルトまたはトラップ、またはクロック割り込みの間に) 配信されます。複数のシグナルの配信準備が同時に整った場合は、トラップで生じたシグナルが先に配信されます。その他のシグナルは、それぞれが前のシグナルのハンドラに対し、最初の命令の前に割り込んだ状態で同時に処理されます。保留になっているシグナルの集合は、 sigpending(2) システムコールで返されます。捕捉されたシグナルが配信されると、スレッドの現在の状態が保存され、新しいシグナルマスクが以下で説明するように算出されて、シグナルハンドラが呼び出されます。ハンドラの呼び出しは、シグナル処理ルーチンが正常に戻った場合に、スレッドがシグナル配信前のコンテキストで実行を再開するように設定されます。スレッドが別のコンテキストでの再開を望む場合は、前のコンテキストそのものを自分自身で回復するように設定する必要があります。

シグナルがスレッドに配信されると、プロセスのシグナルハンドラの実行が続く間 (または sigprocmask(2) システムコールが呼び出されるまで)、新しいシグナルマスクが設置されます。このマスクは、現在のシグナルマスク集合、配信されるシグナル、呼び出されるハンドラに関連したシグナルマスクの和集合を取って形成されます。

sigaction() システムコールは、 sig で指定したシグナルのアクションを割り当てます。 act が 0 でない場合は、アクション ( SIG_DFL, SIG_IGN かハンドラルーチン)、および指定されたシグナルの配信時に使用するマスクが指定されます。 oact が 0 でない場合は、そのシグナルのそれまでの処理情報がユーザに返されます。

struct sigaction の上記の宣言は、リテラルではありません。それは、アクセス可能なメンバをリストするためだけに提供されます。実際の定義については、 < sys/signal.h> を参照してください。特に、sa_handler と sa_sigaction によって占領された記憶域は、オーバラップし、アプリケーションは、同時に両方を使用することはできません。

シグナルハンドラが設置されると、通常の場合は別の sigaction() システムコールを呼び出すか execve(2) を実行するまで、そのシグナルハンドラは設置されたままです。 sa_handlerSIG_DFL に設定することで、シグナルごとに固有なデフォルトアクションにリセットすることができます。デフォルトとは、プロセスの終了 (コアダンプが取られることもあります)、アクションなし、プロセスの停止、プロセスの継続です。それぞれのシグナルのデフォルトアクションについては、下記のシグナルリストを参照してください。 sa_handlerSIG_DFL である場合、シグナルのデフォルトアクションはシグナルの破棄になります。また、シグナルが保留になっている場合でも、シグナルがマスクされていても保留中のシグナルは破棄されます。 sa_handlerSIG_IGN に設定すると、現在のシグナル実体と保留中のシグナル実体は無視されて破棄されます。

オプションは、 sa_flags を設定することで指定できます。それぞれのビットの意味は以下のとおりです:

SA_NOCLDSTOP
SIGCHLD シグナルの受信関数を設置する場合にこのビットを設定すると、子プロセスが停止したときではなく、子プロセスが終了するときにのみ、 SIGCHLD シグナルが生成されます。
SA_NOCLDWAIT
SIGCHLD シグナルで sigaction() を呼び出す場合にこのビットを設定すると、システムは、呼び出し側プロセスの子プロセスが終了したときにゾンビプロセスを作成しなくなります。そのあと、呼び出し側プロセスが wait(2) (かそれに相当する関数) を実行すると、呼び出し側プロセスのすべての子プロセスが終了するまでブロックし、次に errnoECHILD に設定して-1 を返します。 SIGCHLD のための sa_handlerSIG_IGN を設定することによって、ゾンビの作成を避ける同じ効果を得ることも可能です。
SA_ONSTACK
このビットが設定されているなら、システムは、 sigaltstack(2) がある各スレッドによって指定される シグナルスタック のプロセスにシグナルを配信します。
SA_NODEFER
このビットを設定すると、配信済みシグナルのさらなる発生が、ハンドラの実行中にマスクされなくなります。
SA_RESETHAND
このビットを設定すると、シグナルが配信された瞬間に、ハンドラが SIG_DFL にリセットされます。
SA_RESTART
下の段落を参照してください。
SA_SIGINFO
このビットが設定されている場合、ハンドラ関数は、 struct sigaction 構造体の sa_sigaction メンバが指すものと見なします。ハンドラ関数は、先に示したプロトタイプもしくは後で示す 使用例 に一致しなくてはなりません。このビットは、 SIG_DFL もしくは SIG_IGN を割り当てる時には設定してはいけません。

次に挙げるシステムコールの実行中にシグナルが捕捉されると、そのシステムコールの呼び出しは、エラー EINTR で強制終了されるか、要求より短いデータ転送で戻るか、または再開されます。保留中の呼び出しの再開は、 sa_flagsSA_RESTART ビットを設定することによって要求されます。影響を受けるシステムコールは、通信チャネルまたは (通常ファイルではなく端末のような) 遅いデバイスと wait(2) または ioctl(2) の間で open(2), read(2), write(2), sendto(2), recvfrom(2), sendmsg(2)recvmsg(2) を含んでいます。しかしながら、既にコミットされた呼び出しは、再開されませんが、代りに、部分的な成功 (例えば、短い読み込みカウント) を返します。

pthread_create(3) の後に、シグナルマスクは、新しいスレッドと保留中のシグナルのセットによって継承され、新しいスレッドのためのシグナルスタックは、空です。

fork(2) または vfork(2) の後では、すべてのシグナル、シグナルマスク、シグナルスタック、再開フラグ、割込みフラグが子プロセスに継承されます。

execve(2) システムコールは、捕捉されていたすべてのシグナルのデフォルトアクションを元に戻し、すべてのシグナルをユーザスタックで受信されるようにリセットします。無視されたシグナルは無視されたままです。シグナルマスクは同じ状態のままです。保留中のシステムコールを再開する設定のシグナルは、その再開の設定のままです。

以下はすべてのシグナルのリストです。名称は、インクルードファイル < signal.h> にあるものと同じです:

名前 デフォルトの動作 説明
SIGHUP プロセスを終了 端末行のハングアップ
SIGINT プロセスを終了 プログラムに割り込む
SIGQUIT コアイメージを作成 プログラムを終了
SIGILL コアイメージを作成 不正命令
SIGTRAP コアイメージを作成 トラップを追跡
SIGABRT コアイメージを作成 abort(3) の呼び出し (以前は, SIGIOT)
SIGEMT コアイメージを作成 実行されたエミュレート命令
SIGFPE コアイメージを作成 浮動小数点例外
SIGKILL プロセスを終了 プログラムを kill
SIGBUS コアイメージを作成 バスエラー
SIGSEGV コアイメージを作成 セグメンテーション侵害
SIGSYS コアイメージを作成 呼び出された存在しないシステムコール
SIGPIPE プロセスを終了 読み込み側のないパイプに書き込み
SIGALRM プロセスを終了 時間切れのリアルタイムタイマ
SIGTERM プロセスを終了 ソフトウェア終了シグナル
SIGURG シグナルを破棄 ソケット上に存在する緊急状態
SIGSTOP プロセスを停止 停止 (捕捉または無視できない)
SIGTSTP プロセスを停止 キーボードから生成されたシグナルを停止
SIGCONT シグナルを破棄 停止後の継続
SIGCHLD シグナルを破棄 子プロセスの状態が変更された
SIGTSTP プロセスを停止 キーボードから生成されたシグナルを停止
SIGCONT シグナルを破棄 停止後の継続
SIGCHLD シグナルを廃棄 子プロセスの状態が変更された
SIGTTIN プロセスを停止 制御端末から試みられたバックグラウンドの読み込み
SIGTTOU プロセスを停止 制御端末に試みられたバックグラウンドの書き込み
SIGIO シグナルを破棄 記述子で I/O が可能 ( fcntl(2) 参照)
SIGXCPU プロセスの終了 超過した CPU 時間の制限 ( setrlimit(2) を参照)
SIGXFSZ プロセスの終了 超過したファイルサイズの制限 ( setrlimit(2) を参照)
SIGVTALRM プロセスの終了 仮想時間のアラーム ( setitimer(2) を参照)
SIGPROF プロセスの終了 プロファイルのタイマのアラーム ( setitimer(2) を参照)
SIGWINCH シグナルの破棄 ウィンドウサイズの変更
SIGINFO シグナルの破棄 キーボードからの状態要求
SIGUSR1 プロセスの終了 ユーザ定義シグナル 1
SIGUSR2 プロセスの終了 ユーザ定義シグナル 2

act で指定された sa_mask フィールドは、 SIGKILL または SIGSTOP をブロックすることを許可しません。そうする、あらゆる試みは、静かに無視されます。

次の関数は、リエントラントか、またシグナルによって割り込み可能ではなく、非同期シグナルにセーフです。したがって、アプリケーションは、マルチスレッド化されたプロセスで fork(2) を呼び出した後に、シグナル捕獲関数から、または子プロセスから、制限なしで、それらを呼び出すことができます:

基本インタフェース:

_Exit(), _exit(), accept(), access(), alarm(), bind(), cfgetispeed(), cfgetospeed(), cfsetispeed(), cfsetospeed(), chdir(), chmod(), chown(), close(), connect(), creat(), dup(), dup2(), execl(), execle(), execv(), execve(), faccessat(), fchdir(), fchmod(), fchmodat(), fchown(), fchownat(), fcntl(), fork(), fstat(), fstatat(), fsync(), ftruncate(), getegid(), geteuid(), getgid(), getgroups(), getpeername(), getpgrp(), getpid(), getppid(), getsockname(), getsockopt(), getuid(), kill(), link(), linkat(), listen(), lseek(), lstat(), mkdir(), mkdirat(), mkfifo(), mkfifoat(), mknod(), mknodat(), open(), openat(), pause(), pipe(), poll(), pselect(), pthread_sigmask(), raise(), read(), readlink(), readlinkat(), recv(), recvfrom(), recvmsg(), rename(), renameat(), rmdir(), select(), send(), sendmsg(), sendto(), setgid(), setpgid(), setsid(), setsockopt(), setuid(), shutdown(), sigaction(), sigaddset(), sigdelset(), sigemptyset(), sigfillset(), sigismember(), signal(), sigpending(), sigprocmask(), sigsuspend(), sleep(), sockatmark(), socket(), socketpair(), stat(), symlink(), symlinkat(), tcdrain(), tcflow(), tcflush(), tcgetattr(), tcgetpgrp(), tcsendbreak(), tcsetattr(), tcsetpgrp(), time(), times(), umask(), uname(), unlink(), unlinkat(), utime(), wait(), waitpid(), write()。

X/Open システムインタフェース:

sigpause(), sigset(), utimes()。

リアルタイムインタフェース:

aio_error(), clock_gettime(), timer_getoverrun(), aio_return(), fdatasync(), sigqueue(), timer_gettime(), aio_suspend(), sem_post(), timer_settime()。

POSIX によって非同期シグナルにセーフとして指定されない基本的なインタフェース:

fpathconf(), pathconf(), sysconf()。

POSIX によって非同期シグナルにセーフとして指定されない基本的なインタフェースですが、予定されています:

ffs(), htonl(), htons(), memccpy(), memchr(), memcmp(), memcpy(), memmove(), memset(), ntohl(), ntohs(), stpcpy(), stpncpy(), strcat(), strchr(), strcmp(), strcpy(), strcspn(), strlen(), strncat(), strncmp(), strncpy(), strnlen(), strpbrk(), strrchr(), strspn(), strstr(), strtok_r(), wcpcpy(), wcpncpy(), wcscat(), wcschr(), wcscmp(), wcscpy(), wcscspn(), wcslen(), wcsncat(), wcsncmp(), wcsncpy(), wcsnlen(), wcspbrk(), wcsrchr(), wcsspn(), wcsstr(), wcstok(), wmemchr(), wmemcmp(), wmemcpy(), wmemmove(), wmemset()。

拡張インタフェース:

accept4(), bindat(), closefrom(), connectat(), eaccess(), ffsl(), ffsll(), flock(), fls(), flsl(), flsll(), futimesat(), pipe2(), strlcat(). strlcpy(), strsep()。

加えて、 errno を読み込むか、または書き込むことは、非同期シグナルにセーフです。

上記にリストされないすべての関数は、シグナルに関して安全 (セーフ) でないと見なされています。すなわち、そのような関数の振る舞いは、それらが安全でない関数を割り込むシグナルハンドラから呼び出されるとき、未定義です。しかしながら、一般的に、シグナルハンドラは、フラグを設定するだけを行うべきです。その他のアクションは、安全ではありません。

また、グローバル変数 errno のコピーを作り、シグナルハンドラから返る前に、それを復旧することはよいことです。これは、シグナルハンドラの内部から呼び出される関数によって設定されている errno の副作用から保護します。

戻り値

The sigaction() function returns the value 0 if successful; otherwise the value -1 is returned and the global variable errno is set to indicate the error.

使用例

ハンドラが一致する 3 つの指定できるプロトタイプがあります:
ANSI C:
void handler( int);
伝統的な BSD スタイル:
void handler( int, int code, struct sigcontext *scp);
POSIX の SA_SIGINFO:
void handler( int, siginfo_t *info, ucontext_t *uap);

sa_flags フラグ中で SA_SIGINFO ビットが設定されている場合、ハンドラ関数は、 SA_SIGINFO プロトタイプに一致しなくてはなりません。その場合、 struct sigaction 構造体の sa_sigaction メンバがハンドラ関数を指していなければなりません。この方法で SIG_DFL または SIG_IGN を割り当ててはいけないことに注意してください。

SA_SIGINFO フラグが設定されていない場合、ハンドラ関数は ANSI C または伝統的な BSD プロトタイプのどちらかに一致しなくてはならず、 struct sigaction 構造体の sa_handler メンバがハンドラ関数を指していなければなりません。実際には、 FreeBSD は、常に後者である BSD プロトタイプの 3 つの引数を送りますし、 ANSI C プロトタイプはそのサブセットになっていますので、どちらでも動作します。 FreeBSD インクルードファイルの sa_handler メンバ宣言は、 (POSIX の要求に従い) ANSI C のものです。そのため、 BSD スタイルの関数のポインタの場合、警告メッセージを無くしてコンパイルするにはキャストする必要があります。伝統的な BSD スタイルは移植性がなく、その機能性も SA_SIGINFO ハンドラの完全な部分集合になっていますので、 BSD スタイルを使うことは推奨されていません。

sig 引数は、シグナル番号で、 < signal.h>SIG... 値のうちの 1 つです。

BSD スタイルのハンドラの code 引数と SA_SIGINFO ハンドラへの info 引数の si_code メンバには、シグナルの発生理由を説明した数値コードが含まれています。通常、この数値コードは、 < sys/signal.h> にある SI_... 値の 1 つであるか、もしくはシグナルに特化したコード、すなわち SIGFPE に対する FPE_... 値です。

BSD スタイルのハンドラの scp 引数は、 struct sigcontext 構造体のインスタンスを指しています。

POSIX SA_SIGINFO ハンドラの uap 引数は、ucontext_t のインスタンスを指しています。

エラー

sigaction() システムコールは、次の 1 つが発生するなら、失敗し、新しいシグナルハンドラは、インストールされません:
[ EINVAL]
sig 引数が、有効なシグナル番号ではありません。
[ EINVAL]
SIGKILL または SIGSTOP のためのハンドラを無視するか、または供給する試みが行われました。

規格

sigaction() システムコールは、 IEEE Std 1003.1-1990 (“POSIX.1”) に適合するはずです。 SA_ONSTACKSA_RESTART フラグは、シグナル SIGTRAP, SIGEMT, SIGBUS, SIGSYS, SIGURG, SIGIO, SIGXCPU, SIGXFSZ, SIGVTALRM, SIGPROF, SIGWINCHSIGINFO と同様に、Berkeley の拡張です。それらのシグナルは、ほとんどの BSD から派生したシステムで利用可能です。 SA_NODEFERSA_RESETHAND フラグは、他のオペレーティングシステムとの後方互換性のためのものです。 SA_NOCLDSTOPSA_NOCLDWAIT フラグは、他のオペレーティングシステムに共通にある特徴的なオプションです。フラグは、 SIGCHLD を無視することによってゾンビの生成を回避するオプションともに、 Version 2 of the Single UNIX Specification (“SUSv2”) によって承認されています。
September 6, 2013 FreeBSD