您犯了这样一个事实:您本质上是在尝试递归地处理信号。
使用时signal()
要注册信号处理程序,该信号号将被阻止,直到信号处理程序返回 - 实际上,内核/libc 在调用信号处理程序时会阻止该信号号,并在信号处理程序返回后取消阻止它。因为你永远不会从信号处理程序返回(相反,你execl
一个新的二进制文件),SIGUSR1
保持阻塞状态,因此不会第二次被抓住。
这可以通过检查看出/proc/</pid>/status
发送第一个之前和之后SIGUSR1
.
Before:
$ cat /proc/<pid>/status | grep -E "Sig(Cgt|Blk)"
SigBlk: 0000000000000000
SigCgt: 0000000000000200
After:
$ cat /proc/<pid>/status | grep -E "Sig(Cgt|Blk)"
SigBlk: 0000000000000200
SigCgt: 0000000000000200
注意SigCgt
表示信号 10 已注册(该数字是位字段;第 10 位已设置,相当于 SIGUSR1,请参阅man signal(7)
对于数字)。SigBlk
之前是空的SIGUSR
发送到您的进程,但发送信号后它包含SIGUSR1
.
您有两种方法可以解决这个问题:
A)。手动解锁SIGUSR
打电话之前execl
in sighandler
:
sigset_t sigs;
sigprocmask(0, 0, &sigs);
sigdelset(&sigs, SIGUSR1);
sigprocmask(SIG_SETMASK, &sigs);
b). Use sigaction
与SA_NODEFER
标志而不是signal
注册信号处理程序。这将防止SIGUSR1
避免在信号处理程序中被阻塞:
struct sigaction act;
act.sa_handler = signalhandler;
act.sa_mask = 0;
act.sa_flags = SA_NODEFER;
sigaction(SIGUSR1, &act, 0);