我目前正在研究使用sigprocmask
阻止某些信号(在这种情况下,SIGALRM
and SIGCHLD
)当关键代码段正在执行时。与这些信号关联的两个信号处理程序都将访问和修改中央数据结构,因此在主进程处理该数据结构时阻止它们访问它至关重要。
目前,我的计划是简单地在代码关键部分的开头禁用这些信号,然后在最后重新启用它们。
void criticalFunction(void) {
// disable signals with sigprocmask
// critical code
// enable signals with sigprocmask
}
但是,将被阻止的信号的信号处理程序也会调用criticalFunction
。当他们打电话时会发生什么sigprocmask
功能并启用对自己信号的阻塞?他们会停止执行还是继续执行? (或者第三个条件..)
我能找到的关于此的唯一注释如下:
如果在信号处理程序中调用 sigprocmask(),则从
处理程序可以通过恢复原始状态来撤消 sigprocmask() 的工作
待处理信号掩码。
(http://www.mkssoftware.com/docs/man3/sigprocmask.3.asp http://www.mkssoftware.com/docs/man3/sigprocmask.3.asp)
(这是我之前问题的后续问题:信号处理程序访问队列数据结构(竞争条件?) https://stackoverflow.com/questions/8146108/signal-handler-accessing-queue-data-structure-race-condition)
请记住,信号处理程序内的默认行为是阻止正在处理的信号。此外,当在信号处理程序内部进行函数调用时,您只想调用信号安全函数。照这样说,sigprocmask()
is a 信号安全功能 https://www.securecoding.cert.org/confluence/display/seccode/SIG30-C.+Call+only+asynchronous-safe+functions+within+signal+handlers,如果您使用它来阻止被内部调用的信号处理程序阻止的相同信号,那么实际上什么都不会发生......您将保留当前相同的信号掩码有。唯一的区别是,在信号处理程序内部,只有任一信号SIGALRM
or SIGCHLD
保证被阻止(这取决于您所在的信号处理程序),当您调用时sigprocmask()
要阻止这些特定信号,呼叫后这两个信号都将被阻止。
需要注意的是代码的第二部分criticalFunction
当你尝试打电话时sigprocmask()
to enable当前在信号掩码中被阻止的信号。这可能会造成这样一种情况:您最终会在对信号处理程序的调用中出现一定程度的重入。换句话说,为您所在的信号处理程序启用信号可能意味着在您退出当前信号处理程序之前,另一个SIGALRM
or SIGCHLD
被捕获,您将再次重新进入信号处理程序来处理这个新捕获的信号。只要您在任何关键部分更新后启用信号,那么我认为您应该可以适应这种可重入的情况,但为了安全起见,您可能只想在criticalFunction
在最后criticalFunction
,而不是中间的某个地方,当你从criticalFunction
,不要做任何不异步安全的事情......你必须假设第二个返回后的任何代码sigprocmask()
可能没有按顺序执行(即,它可能在捕获第二个信号并且运行其信号处理程序后执行)。
如果您尝试从exec
家庭,或者信号处理程序中类似的东西。会发生的情况是,新覆盖的进程将从当前进程继承信号掩码,因此如果当前进程阻止了某些信号,那么它们也会在新进程中被阻止。因此,如果新进程假设信号已畅通,则新进程中的信号处理程序将永远不会运行。
顺便说一句,一个警告:不要混合信号和线程!您在问题中提到“主进程”......我希望这并不意味着您试图混合信号和线程。如果是这样,那就需要一个非常具体的习惯用法,否则你会造成各种破坏。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)