sigaction()にフラグを設定した際の動作についてどう挙動が変わるかについての検証を行なったのでその時のメモ。
検証環境
Ubuntu 18.04.4
gcc 9.3.0
SA_RESETHANDを設定した場合
SA_RESETHANDを設定した場合シグナルは、シグナルを捕捉するたびにデフォルトの設定に変更してから、シグナル処理を行う。本来であればSA_RESETHANDを設定しない場合、プロセス実行中はsigaction()で設定された処理が継続して実行される。
※検証のため「act.sa_flags = SA_RESETHAND | SA_RESTART;」をコメントアウトして実行する。
sigaction_demo.c
/* コンパイル: gcc -o sigaction_demo sigaction_demo.c */
# include <signal.h>
# include <stdio.h>
# include <unistd.h>
# include <stdlib.h>
# include <string.h>
# define INPUTLEN 100
/* Ctrl+Cで呼び出される処理 */
static void t_handler()
{
printf("シグナルハンドラが呼ばれました。3秒間スリープします\n");
sleep(3);
printf("シグナルハンドラを終了します\n");
}
int main(){
int nchars;
char input[INPUTLEN];
struct sigaction act;
act.sa_handler = t_handler;
/* シグナル捕捉時デフォルト設定に変更 */
/* 検証としてコメントアウトしている */
// act.sa_flags = SA_RESETHAND | SA_RESTART;
act.sa_flags = SA_RESTART;
if (sigaction(SIGINT, &act, NULL) == -1)
exit(EXIT_FAILURE);
pause();
}
シグナルで割り込みをしてもSIGINTを関数呼び出しにしているため、強制終了させられない。
実行例
# (CTrl+Cを押す)
^Cシグナルハンドラが呼ばれました。3秒間スリープします
シグナルハンドラを終了します
# (Ctrl+Cを押す)
^Cシグナルハンドラが呼ばれました。3秒間スリープします
シグナルハンドラを終了します
# (Ctrl+\を押す)
^\終了 (コアダンプ)
検証用のコメントアウトを外した場合(上記ソースコードを下記のように変更する)
act.sa_flags = SA_RESETHAND | SA_RESTART;
//act.sa_flags = SA_RESTART;
実行例
# (CTrl+Cを押す)
^Cシグナルハンドラが呼ばれました。3秒間スリープします
シグナルハンドラを終了します
# (CTrl+Cを押す)
^C
1回目のシグナル捕捉後関数が呼ばれているが、2回目にシグナルを捕捉した時にはデフォルト設定の強制終了に戻っているのがわかる。
参考資料
・『Linuxプログラミングインタフェース』
・『Unix/Linuxプログラミング理論と実践』