2019年7月21日日曜日

bash でシグナル trap 中に更にシグナルを受けたらどうなるか?

bash でシグナル trap 中に更にシグナルを受けたらどうなるか? を確認したいと思い、実験してみました。
#!/bin/bash

SELF_PID=$$

sig_HUP_handler() {
        echo caught SIGHUP
        kill -TERM $SELF_PID
}

trap "echo caught SIGTERM ; exit 1" SIGTERM
trap "sig_HUP_handler     ; exit 2" SIGHUP

kill -HUP $SELF_PID

exit 0
このスクリプトを実行して確認してみたら、終了コードが 2 でした。つまり、SIGTERM に対する trap は実行されませんでした。
[root@hoge ~]# ./trap_test.bash 
caught SIGHUP
[root@hoge ~]# echo $?
2
[root@hoge ~]# strace ./trap_test.bash 
...
kill(9607, SIGHUP)                      = 0
--- SIGHUP {si_signo=SIGHUP, si_code=SI_USER, si_pid=9607, si_uid=0} ---
rt_sigreturn({mask=[]})                 = 0
rt_sigprocmask(SIG_BLOCK, [HUP], [], 8) = 0
rt_sigprocmask(SIG_BLOCK, NULL, [HUP], 8) = 0
rt_sigprocmask(SIG_BLOCK, NULL, [HUP], 8) = 0
fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 0), ...}) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f0264e7a000
write(1, "caught SIGHUP\n", 14caught SIGHUP
)         = 14
kill(9607, SIGTERM)                     = 0
--- SIGTERM {si_signo=SIGTERM, si_code=SI_USER, si_pid=9607, si_uid=0} ---
rt_sigreturn({mask=[HUP]})              = 0
rt_sigprocmask(SIG_SETMASK, [HUP], NULL, 8) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
exit_group(2)                           = ?
+++ exited with 2 +++
[root@hoge ~]# 
strace をかけてみると、このように SIGTERM は確かに割り込んでいます。次に、exit 2 を行わないようにして、実験してみました。
[root@hoge ~]# diff trap_test.bash trap_test2.bash 
11c11
< trap "sig_HUP_handler     ; exit 2" SIGHUP
---
> trap "sig_HUP_handler     # exit 2" SIGHUP
[root@hoge ~]# ./trap_test2.bash 
caught SIGHUP
caught SIGTERM
[root@hoge ~]# echo $?
1
終了コードは 1 になりました。つまり、SIGHUP に対する trap 完了後に、SIGTERM に対する trap が実行されました。
なお、上記の実験環境は、CentOS7 bash-4.2.46-31.el7.x86_64 です。同じスクリプトを RHEL4 より古い環境で動かすと bash が segfault してしまいます。当時は、想定されていなかったのでしょうね。 シグナルには気をつけよう!

0 件のコメント:

コメントを投稿

人気ブログランキングへ にほんブログ村 IT技術ブログへ