【问题标题】:sigprocmask( ) blocking signals in UNIXsigprocmask() 在 UNIX 中阻塞信号
【发布时间】:2023-03-09 21:37:01
【问题描述】:

我写了一小段代码。此代码首先阻止 {SIGSEGV},然后将 SIGRTMIN 添加到同一组。所以,我的最终信号集是 {SIGSEGV,SIGRTMIN}。因此,如果我使用 SIG_UNBLOCK,根据我的理解,首先应该解锁 SIGRTMIN,然后如果我调用 SIG_UNBLOCK,则应该解锁 SIGSEGV。

即 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)

【问题讨论】:

    标签: c unix signals sigprocmask


    【解决方案1】:

    你的前提是错误的。只需调用sigprocmask,整个集合就会被阻止和解除阻止。

    此外,通常您会创建一个包含您想要阻止的每个信号的集合,然后您会尝试使用 sigprocmask(SIG_BLOCK, pointer_to_sigset); 阻止所有信号。

    您的代码并没有真正解除对 SIGSEGV 的阻止。这是我在没有错误处理的情况下编写的内容,因为它会使 sn-p 不必要地长。检查每个功能 但是,对于错误,可能的错误列表由手册页提供:

    /* ... */
    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 */
    

    当然,您可能希望将阻塞信号拆分为不同集合上的两个操作。该机制的工作原理如下:有一组阻塞信号,如果您提供 oldset 参数,它将替换 oldset。您可以使用SIG_BLOCK 添加到该集合,使用SIG_UNBLOCK 从该集合中删除,并使用sigprocmask 函数的SIG_SETMASK 参数更改整个集合。

    【讨论】:

    • @kubi:那为什么我没有收到 SIGSEGV?
    • @kubi: 不,我不认为整个系列都可以一口气畅通无阻。检查链接:stackoverflow.com/questions/25261/help-with-sigprocmask。而且,sigprocmask( ) 本身并没有阻塞或解除阻塞,它是参数或第一个参数使它执行阻塞、解除阻塞或屏蔽。所以,在指错我之前请三思。
    • @kingsmasher1:你如何处理SIGSEGV?您可以粘贴信号处理程序代码的 sn-p 吗?信号是否正确发送?查看sigprocmaskkill的错误码。
    • @kingsmasher1:sigprocmask 的手册页在这个主题上非常清楚。下面是一段摘录: SIG_BLOCK - 阻塞信号的集合是当前集合和集合参数的并集。 SIG_UNBLOCK - set 中的信号从当前的阻塞信号集中移除。众所周知,集合并集和差集不会一次更改一个元素。
    • @kubi:我没有处理它,我希望默认处理程序 todoit,并停止我的代码。是的,信号被正确发送,因为如果我注释掉 SIGSEGV 的 sigaddset 代码,程序停止并收到 SIGSEGV(行为正确)
    【解决方案2】:

    正如 kubi 指出的:这是修改后的代码,问题是,我搞砸了 old_set 和 new_set。 SIGSEGV 被添加到 old_set 中,它没有被解锁,因此我没有收到分段错误(SIGSEGV 信号)。 感谢 kubi。

    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");
     }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-10-16
      • 2016-05-24
      • 2016-02-08
      • 1970-01-01
      • 2011-08-24
      相关资源
      最近更新 更多