题
我写一个系统关键程序用于一个Linux发行版本,我的发展。它需要重新启动本身关于接收某些信号,要尽量避免崩溃。问题是,在重新启动之后,我无法重新启用这一信号。那是信号不能接受的两倍。后execv()'ing本身,当新的处理呼叫的信号()设立的信号,SIG_DFL返回。每一个时间。甚至如果我把它连续两次--表示,它从来就不是设置在首位。是有些怪异的标志正在进行从原来的过程?
解决方案
你正在下降,恶的事实,你基本上是试图递归的把手一个信号。
当使用 signal()
注册一个信号处理程序,这一信号被阻断,直到信号处理返回的效果的核心/libc块,信号的时候信号处理程序,以及取消阻止它后信号处理程序的返回。因为你永远不会返回自信号处理程序(而不是你 execl
一个新的二进制), SIGUSR1
保持封锁和所以不是抓到2的时间。
这可以看出,通过检查 /proc/</pid>/status
之前和之后你发送第一 SIGUSR1
.
之前:
$ cat /proc/<pid>/status | grep -E "Sig(Cgt|Blk)"
SigBlk: 0000000000000000
SigCgt: 0000000000000200
之后:
$ 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
在 sighandler
:
sigset_t sigs;
sigprocmask(0, 0, &sigs);
sigdelset(&sigs, SIGUSR1);
sigprocmask(SIG_SETMASK, &sigs);
b)。使用 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);
其他提示
信号处理程序不会在exec
之间继承,因为SIG_IGN
会覆盖整个地址空间,而任何未重置的信号处理程序都将指向错误的位置。它没有被重置的唯一时间是它被设置为,例如,<=>,这不依赖于前 - <=>过程的地址空间。