【问题标题】:Signals in the "set" parameter of sigtimedwait() not getting deliveredsigtimedwait() 的“set”参数中的信号未传递
【发布时间】:2016-08-09 01:42:44
【问题描述】:

我最近一直在研究 Linux 上的信号处理,并阅读了与信号处理相关的所有概念。一个让我头疼的问题是,为什么 sigtimedwait() 集中的信号在进程畅通时没有得到传递。我的代码如下:-

#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
void sighandler1(int sig)
{
        printf("SIGINT caught\n");
}
void sighandler2(int sig)
{
        printf("SIGTSTP caught\n");
}
void sighandler3(int sig)
{
        printf("SIGALRM caught\n");
}

int main()
{

  sigset_t s1,s2;

  struct sigaction act1,act2,act3;

  int ret;

  sigemptyset(&s1);// The bit-mask s1 is cleared
  sigaddset(&s1,SIGINT);//Add SIGINT to the bit-mask s1

  sigemptyset(&s2);// The bit-mask s2 is cleared
  sigaddset(&s2,SIGALRM);//Add SIGALRM to the bit-mask s2

  sigprocmask(SIG_BLOCK,&s2,NULL);//Signal(s) in s2 blocked

  act1.sa_handler = sighandler1; //function pointer pointing to the signal handler
  act1.sa_flags = 0;        

  sigaction(SIGINT,&act1,NULL);  // installing the action
                                 // for SIGINT

  act2.sa_handler = sighandler2; //function pointer pointing to another signal handler
  act2.sa_flags = 0;         // no flags


  sigaction(SIGTSTP,&act2,NULL);  // installing the action
                                 // for SIGTSTP
  act3.sa_handler = sighandler3; //function pointer pointing to another signal handler
  act3.sa_flags = 0;         // no flags


  sigaction(SIGALRM,&act3,NULL);  // installing the action for SIGALRM

  sigprocmask(SIG_SETMASK,&s1,NULL); //Signals in s1 blocked and other signals unblocked
  printf("sigprocmask() called with SIG_SETMASK on s1,which contains SIGINT\n");
  printf("Blocked on sigtimedwait() with s1\n");
  if(sigtimedwait(&s1,NULL,NULL) < 0)
        {
                if(errno ==  EINTR)
                printf("Some other signal caught\n");
        }
  printf("This is a process. You can pass signal to it\n");

  while(1);

}

为了更清楚地说明这个问题,我在上面的代码中调用了 sigtimedwait,并将“s1”作为“set”参数。该集合仅包含信号 SIGINT。根据手册页, sigtimedwait() 会阻止进程,直到传递其集合中的一个信号。我对这个说法没意见。但是为什么当我通过 SIGINT 来解锁进程时没有调用 SIGINT 处理程序?另一方面,当我传递集合中不存在的 SIGALRM 或 SIGTSTP 时,EINTR 会按预期返回,并且信号处理程序也会被调用。

对于任何想观察场景的人,都可以执行上述代码,然后将 SIGINT 传递给它。他们将观察到进程在没有调用处理程序的情况下被解除阻塞。为什么不调用处理程序?我是否误解了 sigtimedwait() 手册页的任何部分??

【问题讨论】:

  • 有人可以调查一下吗?提前致谢。

标签: linux signals signal-handling sigaction sigprocmask


【解决方案1】:

sigtimedwait 似乎返回信号值,而不是信号处理程序被捕获:

switch(sigtimedwait(&s1,NULL,NULL))
{
    default:
        printf ("Some other signal???");
        break;
    case SIGINT:
        printf ("We got SIGINT\n");
        break;
    case -1:
        perror ("sigtimedwait");
        break;
}

【讨论】:

  • 查看手册页,这是意料之中的:sigwaitinfo() 将信号从待处理信号集中移除,并将信号编号作为其函数结果返回。如果 info 参数不为 NULL,则它指向的缓冲区用于返回 siginfo_t 类型的结构(请参阅 sigaction(2)),其中包含有关信号的信息。
  • 那么,手册页中DESCRIPTION的第一行中提到的以下语句呢 - sigwaitinfo() 暂停调用线程的执行,直到传递 set 中的一个信号. 它确实说必须传递信号。但是,我看到集合中的信号没有被传递,但是信号不在集合中被传递,处理程序被调用。
  • 您只在 sigprocmask() 调用中阻止 SIGINT,这就是其他信号可以通过的原因(导致 sigtimedwait 返回 -1 并将 errno 设置为 EINTR)。在 sigtimedwait 之后,SIGINT 仍然被阻塞,并且无法被接收。交付的措辞意味着它不再位于内核队列中。在这种情况下,sigtimedwait 是信号的接收者。
  • 好的,我不阻止 SIGINT。因此,即使我注释了以下行 sigprocmask(SIG_SETMASK,&s1,NULL); ,当进程被解除阻塞时,信号 SIGINT 仍然没有得到传递。虽然它稍后会在 sigtimedwait() 上不再阻塞进程时交付。那么这是怎么回事呢?
  • 你的声明是什么意思 - 他们的意思是它不再在内核队列中。在这种情况下,sigtimedwait 是信号的接收者。 这是否意味着 sigtimedwait() 只负责捕获信号而不将其传递给处理程序?类似的东西?
猜你喜欢
  • 1970-01-01
  • 2012-04-24
  • 1970-01-01
  • 2017-08-27
  • 1970-01-01
  • 2013-05-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多