シグナル関数 (signal.h)

void (*signal( int sig, void(*hdlr)(int) ))(int);

シグナルに対する応答を登録します。登録を定義する void func( int ) 型のハンドラ関数を第 2 引数に指定します。これまで登録されていたハンドラ関数へのポインタが返されます。signal

関数のプロトタイプは、次のように記述しても同じです。
typedef void (*_sighdlr_t)( int );
_sighdlr_t signal( int sig, _sighdlr_t hdlr );

sig には、次のいずれかの定数を使用して、シグナルの種類を指定します。

定数 意味
SIGABRT 異常終了。abort から呼び出されます。
SIGFPE 0 による除算
SIGILL 不正な命令
SIGINT 割り込み
SIGSEGV 不正なメモリ アクセス
SIGTERM 終了要求
_SIGNULLPTR NULL ポインタへの代入。_nullptr_chk から呼び出されます。
_SIGSTKOVER スタック オーバーフロー。_stack_chk から呼び出されます。

先頭に下線 (_) が付いている定数は、ISO/JIS/ANSI 規格外です。

初期状態では、すべてのシグナルに対して、それぞれ既定のハンドラ関数が定義されています。 既定のハンドラ関数の動作は、-os によって異なります。-os:dos が有効な場合は、ランタイム エラー を stderr に表示した後、_exit( EXIT_FAILURE ) でプログラムを終了します。-os:none が有効な場合は、何も行わずに呼び出し側に戻ります。

hdlr には、ハンドラ関数か、次のいずれかの定数を指定します。

定数 意味
SIG_DFL 既定のハンドラに戻します。
SIG_IGN このシグナルを無視することを指定します。

ハンドラ関数の引数には、発生したシグナルを示す SIGxxx 値が渡されます。このため、1 つのハンドラ関数で複数の種類のシグナルを区別して処理できます。

登録したハンドラ関数は、一度しか使用されません。つまり、あるシグナルが発生してハンドラ関数が呼び出されると、そのシグナルのハンドラは、SIG_DFL に戻ります。同じハンドラを引き続き使用するには、ハンドラ関数の中で signal を呼び出し、自らを再び登録する必要があります。

Light C では、ユーザーが明示的に該当する SIG??? 値を指定して raise 関数を呼び出さない限り、SIGABRT、_SIGNULLPTR、_SIGSTKOVER 以外のシグナルは起動されません。

int raise( int sig );

現在登録されているハンドラ関数を呼び出します。sig には、signal 関数の sig 引数と同じ定数を指定します。sig に対するハンドラは、この後既定に戻ります。
void handler( int sig ) { printf( "abort!\n" ); }
main() {
  signal( SIGABRT, handler );
  abort(); // 登録ハンドラが消費される
  abort(); // 再び既定のハンドラが使用される
}
結果
abort!
R.1100 abnormal termination