C语言 sigprocmask() 在 UNIX 中阻塞信号
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5288910/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
sigprocmask( ) blocking signals in UNIX
提问by kingsmasher1
i have written a small piece of code. This code first blocks the {SIGSEGV}, then adds SIGRTMIN to the same set. So, my final signal set is, {SIGSEGV,SIGRTMIN}. Thus, if i use SIG_UNBLOCK, as per my understanding, first SIGRTMIN should be unblocked, and then again if i invoke SIG_UNBLOCK, SIGSEGV should be unblocked.
我写了一小段代码。此代码首先阻塞 {SIGSEGV},然后将 SIGRTMIN 添加到同一组。所以,我的最终信号集是 {SIGSEGV,SIGRTMIN}。因此,如果我使用 SIG_UNBLOCK,根据我的理解,首先 SIGRTMIN 应该被解锁,然后如果我调用 SIG_UNBLOCK,SIGSEGV 应该被解锁。
That is, 1) {SIGSEGV,SIGRTMIN} 2) SIG_UNBLOCK = unblock SIGRTMIN, 3) Again invoke SIG_UNBLOCK = unblock SIGSEGV. I am giving the process a SIGRTMIN only, thus my second unblock should halt the process with SIGRTMIN. But it is not. Please help. N.B: Please don't give links to answers of other questions on sigprocmask( ), i have seen them and they don't clarify my question.
也就是说,1) {SIGSEGV,SIGRTMIN} 2) SIG_UNBLOCK = unblock SIGRTMIN, 3) 再次调用SIG_UNBLOCK = unblock SIGSEGV。我只给进程一个 SIGRTMIN,因此我的第二次解除阻塞应该用 SIGRTMIN 停止进程。但事实并非如此。请帮忙。 注意:请不要在 sigprocmask() 上提供指向其他问题答案的链接,我已经看过它们,但它们没有澄清我的问题。
enter code here
#include <signal.h>
#include <unistd.h>
#include <stdio.h>
int main()
{
sigset_t old_set,new_set;
sigemptyset(&old_set);
sigemptyset(&new_set);
if(sigaddset(&old_set,SIGSEGV)==0)
{
printf("sigaddset successfully added for SIGSEGV\n");
}
sigprocmask(SIG_BLOCK,&old_set,NULL); // SIGSEGV signal is masked
kill(0,SIGSEGV);
//*****************************************************************
if(sigaddset(&new_set,SIGRTMIN)==0)
{
printf("sigaddset successfully added for SIGRTMIN\n");
}
sigprocmask(SIG_BLOCK,&new_set,&old_set); // SIGRTMIN signal is masked
kill(0,SIGSEGV);
//****************** Unblock one signal at a time ******************
sigprocmask(SIG_UNBLOCK,&new_set,&old_set); // SIGRTMIN signal is unmasked
sigprocmask(SIG_UNBLOCK,&new_set,&old_set); // SIGSEGV signal is unmasked
}
}
Output:
[root@dhcppc0 signals]# ./a.out
sigaddset successfully added for SIGSEGV
sigaddset successfully added for SIGRTMIN
(Note:SIGSEGV is not received even after sigprocmask(SIG_UNBLOCK,&new_set,&old_set); a second time)
回答by kubi
Your premise is wrong. The whole set gets blocked and unblocked with a single call of sigprocmask.
你的前提是错误的。整个集合通过一次调用就被阻塞和解除阻塞sigprocmask。
Also, normally you would create a set containing every signal you want to block, then you would attempt to block them all with sigprocmask(SIG_BLOCK, pointer_to_sigset);.
此外,通常您会创建一个包含要阻止的每个信号的集合,然后尝试使用sigprocmask(SIG_BLOCK, pointer_to_sigset);.
Your code doesn't really unblock SIGSEGV though. Here's what i would write WITHOUT error handling, because it would make the snippet unnecessarily long. Check every function for errors though, the lists of possible errors are provided by man pages:
不过,您的代码并没有真正解除对 SIGSEGV 的阻止。这是我在没有错误处理的情况下编写的内容,因为它会使代码段变得不必要地长。检查每个函数是否有错误,手册页提供了可能的错误列表:
/* ... */
sigset_t signal_set; /* We don't need oldset in this program. You can add it,
but it's best to use different sigsets for the second
and third argument of sigprocmask. */
sigemptyset(&signal_set);
sigaddset(&signal_set, SIGSEGV);
sigaddset(&signal_set, SIGRTMIN);
/* now signal_set == {SIGSEGV, SIGRTMIN} */
sigprocmask(SIG_BLOCK, &signal_set, NULL): /* As i said, we don't bother with the
oldset argument. */
kill(0,SIGSEGV);
kill(0,SIGSEGV); /* SIGSEGV is not a realtime signal, so we can send it twice, but
it will be recieved just once */
sigprocmask(SIG_UNBLOCK, &signal_set, NULL); /* Again, don't bother with oldset */
/* SIGSEGV will be received here */
Of course, you might want to split blocking the signals into two operations on separate sets. The mechanism works like this: there is some set of blocked signals, which would replace oldset if you provided an oldset argument. You can add to that set with SIG_BLOCK, remove from that set with SIG_UNBLOCK, and change the whole set to your liking with SIG_SETMASKarguments of the sigprocmaskfunction.
当然,您可能希望将阻塞信号拆分为不同集合上的两个操作。该机制是这样工作的:有一些阻塞的信号集,如果你提供了一个 oldset 参数,它们将替换 oldset。您可以使用 向该集合中添加,使用SIG_BLOCK将其从该集合中删除SIG_UNBLOCK,并使用SIG_SETMASK该sigprocmask函数的参数根据您的喜好更改整个集合。
回答by kingsmasher1
As kubi pointed out: Here is the modified code, problem is that, i messed up with old_set and new_set. The SIGSEGV was added in old_set, which was not unblocked, and hence i did not receive Segmentation fault (SIGSEGV signal). Thanks to kubi.
正如 kubi 指出的:这是修改后的代码,问题是,我搞砸了 old_set 和 new_set。SIGSEGV 被添加到 old_set 中,它没有被解锁,因此我没有收到分段错误(SIGSEGV 信号)。感谢库比。
enter code here
#include <signal.h>
#include <unistd.h>
#include <stdio.h>
int main()
{
sigset_t old_set,new_set;
sigemptyset(&old_set);
sigemptyset(&new_set);
if(sigaddset(&old_set,SIGSEGV)==0)
{
printf("sigaddset successfully added for SIGSEGV\n");
}
sigprocmask(SIG_BLOCK,&new_set,&old_set); // SIGSEGV signal is masked
kill(0,SIGSEGV);
//*****************************************************************
if(sigaddset(&new_set,SIGRTMIN)==0)
{
printf("sigaddset successfully added for SIGRTMIN\n");
}
if(sigprocmask(SIG_BLOCK,&new_set,&old_set)==-1) // SIGRTMIN signal is masked
{
perror("sigprocmask");
}
kill(0,SIGSEGV);
//****************** Unblock all signals ******************
if(sigprocmask(SIG_UNBLOCK,&new_set,&old_set)==-1) // SIGRTMIN signal is unmasked
{
perror("sigprocmask");
}
}

