在C中阻塞sa_处理程序中的SIGINT

在C中阻塞sa_处理程序中的SIGINT,c,C,我正在尝试编写一个程序,该程序将设置一个警报10秒,在这10秒后阻止SIGINT,设置另一个警报10秒,取消阻止并忽略SIGINT,然后设置另一个警报10秒,然后终止。我希望我可以在SIGALRM的sa_处理程序中完成所有操作,但它没有像我希望的那样工作。有可能做到这一点吗? 编辑:在SIGALRM的sa处理程序中,我无法将SIGINT设置为blocked #include <stdlib.h> #include <stdio.h> #include <signal

我正在尝试编写一个程序,该程序将设置一个警报10秒,在这10秒后阻止SIGINT,设置另一个警报10秒,取消阻止并忽略SIGINT,然后设置另一个警报10秒,然后终止。我希望我可以在SIGALRM的sa_处理程序中完成所有操作,但它没有像我希望的那样工作。有可能做到这一点吗? 编辑:在SIGALRM的sa处理程序中,我无法将SIGINT设置为blocked

#include <stdlib.h>
#include <stdio.h>
#include <signal.h>
#include <unistd.h>

int ctrlct = 0;
int alrmct = 0;

void catchctrlc(int signo)
{
  printf("Caught CTRL-C! <%d>\n", ++ctrlct);
}

void catchalrm(int signo)
{
  sigset_t alrmset;
  switch(alrmct)
  {
    case 0:
      printf("Alarm 1\n");
      if( (sigemptyset(&alrmset) == -1) || (sigaddset(&alrmset, SIGINT) == -1) )
        printf("Failed to add SIGINT to the alrmset");
      else if( sigprocmask(SIG_BLOCK, &alrmset, NULL) == -1 )
        printf("Failed to block SIGINT");
      break;
    case 1:
      printf("Alarm 2\n");
      break;
    case 2:
      printf("Alarm 3\n");
      exit(EXIT_SUCCESS);
      break;
    default:
      break;
  }
  alrmct++;
  alarm(10);
}

int main(void)
{
  struct sigaction ctrlact, alrmact;
  ctrlact.sa_handler = catchctrlc;
  ctrlact.sa_flags = 0;
  alrmact.sa_handler = catchalrm;
  alrmact.sa_flags = 0;

  /* Install signal handler for CTRL-C */
  if((sigemptyset(&ctrlact.sa_mask) == -1) || (sigaction(SIGINT, &ctrlact, NULL) == -1))
    perror("Failed to set sa_handler for SIGINT");
  /* Install signal handler for SIGALRM */
  if((sigemptyset(&alrmact.sa_mask) == -1) || (sigaction(SIGALRM, &alrmact, NULL)== -1))
    perror("Failed to set sa_handler for SIGALRM");

  alarm(10);
  while(1){}

  return 0;
}
#包括
#包括
#包括
#包括
int ctrlct=0;
int alrmct=0;
无效捕手信用证(内部签名)
{
printf(“按下CTRL-C!\n键,++CTRL-LCT键);
}
无效捕集器(内部签名)
{
信号集;
开关(alrmct)
{
案例0:
printf(“报警1\n”);
if((sigeEmptySet(&alrmset)=-1)| |(sigaddset(&alrmset,SIGINT)=-1))
printf(“未能将SIGINT添加到alrmset”);
else if(sigprocmask(SIG_块和alrmset,NULL)=-1)
printf(“阻止SIGINT失败”);
打破
案例1:
printf(“报警2\n”);
打破
案例2:
printf(“报警3\n”);
退出(退出成功);
打破
违约:
打破
}
alrmct++;
警报(10);
}
内部主(空)
{
结构SIGACTRACT,alrmact;
ctrlact.sa_handler=catchctrlc;
ctrlact.sa_标志=0;
alrmact.sa_handler=catchalrm;
alrmact.sa_标志=0;
/*安装CTRL-C的信号处理程序*/
if((SIGEptySet(&ctrlact.sa_mask)=-1)| |(sigaction(SIGINT,&ctrlact,NULL)=-1))
perror(“未能为SIGINT设置sa_处理程序”);
/*为SIGALRM安装信号处理程序*/
if((sigemptyset(&alrmact.sa_mask)=-1)| |(sigaAction(SIGALRM,&alrmact,NULL)=-1))
perror(“未能为SIGALRM设置sa_处理程序”);
警报(10);
而(1){}
返回0;
}

当发送信号时,内核将->阻塞的信号保存到信号帧中,将发送的信号添加到->阻塞集(除非指定了SA_NODEFER),并在处理完信号返回后,将->阻塞集恢复到信号帧中的一个,从而覆盖所做的任何更改

如果需要这种行为,我们可以通过在信号帧(位于用户线程堆栈上)上编辑保存的信号来克服它。为此,我们需要为报警处理程序指定sau SIGINFO标志,然后:

void catchalrm(int signo, siginfo_t * info, ucontext_t * context)
{

    sigaddset(&context->uc_sigmask, SIGINT);
    ...
}
例如,从信号返回时,恢复的->阻塞集将包含SIGINT


请注意,此行为可能是linux和特定于体系结构的。

不要使用忙循环(
,而(1){}
)使用
pause()
。当被信号中断时,它将返回,并将
errno
设置为
EINTR
。可以在
pause()
周围放置一个循环。只有一组有限的函数可以从信号处理程序安全地调用
printf()
肯定不是这些函数之一。看。
它没有像我希望的那样工作
那么它是如何工作的呢?你发布的代码有问题吗?这是什么?请参阅,您应该确保两个
struct sigaction
变量的
sa_mask
字段设置正确。