この関数の目的
signal()は、シグナルハンドラをセットする。
定義
#include <signal.h> void (*signal(int sig, void (*func)(int)))(int);
働き
signal 関数は sig で指定されるシグナルを受け取った時に、どう扱うかを3つの手段から選ぶ。
func の値が SIG_DFL
であれば、既定の対応をする。
SIG_IGN
であれば、そのシグナルは無視される。
どちらでもなければ、 func は関数へのポインタと見なされ、その関数はシグナル発生時に呼ばれるものとして設定される。
シグナルが発生すると、 func が関数を指す場合には、最初に signal(sig, SIG_DFL);
と等価の処理が実行されるか、処理系定義のシグナルの中断が実行される。
( sig の値が SIGILL
であれば、 SIG_DFL
の処理が実行されるかどうかは処理系定義である。)
次に、(*func)(sig);
と等価の処理が実行される。
func の関数は、 return 文、 abort() 、 exit() 、 longjmp() の呼び出しによって中断されうる。
sig の値が SIGFPE
または処理系定義の計算上の例外であり、 return 文が実行されたときは、
動作は未定義である。そうでなければ、プログラムは中断した地点から再開する。
シグナルが abort() か raise() の呼び出しによって起こったものであれば、使われたシグナルの番号を引数に取る signal() 自身以外の標準ライブラリ関数の呼び出し、
および volatile sig_atomic_t
型の静的変数に値を代入する以外の静的変数への参照による動作は未定義である。
また、 SIG_ERR
の返却に終わる signal() の呼び出しでは、 errno
の値は不定になる。
プログラム開始時には、
signal(sig, SIG_IGN);
と等価の処理がいくつかのシグナルについてなされ、
signal(sig, SIG_DFL);
と等価の処理が他の全ての処理系により定義されているシグナルについてなされる。
処理系は、どのライブラリ関数も signal() を呼ばないように動作しなければならない。
解説
signal.hで解説している通り、signal()はシグナルハンドラに対応する関数をセットする。 セットされた関数が返ると、普通は中断された途中から再開する。
宣言が読みにくいが、こう翻訳できる。(MinGW gccの標準ヘッダーより)
typedef void (*__p_sig_fn_t)(int); __p_sig_fn_t signal(int sig, __p_sig_fn_t func);
ここで、__p_sig_fn_tは、「void (int)型へのポインタ」型である。つまり関数のポインタとなる。
signal()の第2引数に関数へのポインタを渡すかわりに、以下のマクロを使うこともできる。
返り値は、関数のセットが成功すればその関数のポインタ値、成功しなければSIG_ERRである。 成功しなかった場合は正の数がerrnoにセットされる。