C SIGALRM处理程序在另一个处理程序内时不运行

C SIGALRM处理程序在另一个处理程序内时不运行,c,signals,alarm,C,Signals,Alarm,因此,我正在为一个类做一个关于信号的作业,我们的目标是捕获SIGINT信号,并在用户输入Ctrl-C 5次时请求退出。如果用户在十秒钟内没有回复退出提示,它应该自动退出 我的实现是在不屏蔽SIGALRM的情况下为SIGINT设置一个处理程序,然后从SIGINT处理程序内部调用alarm(),但是从我得到的输出来看,似乎直到SIGINT处理程序运行完毕,SIGALRM处理程序才运行 #include <stdio.h> /* standard I/O functions

因此,我正在为一个类做一个关于信号的作业,我们的目标是捕获SIGINT信号,并在用户输入Ctrl-C 5次时请求退出。如果用户在十秒钟内没有回复退出提示,它应该自动退出

我的实现是在不屏蔽SIGALRM的情况下为SIGINT设置一个处理程序,然后从SIGINT处理程序内部调用
alarm()
,但是从我得到的输出来看,似乎直到SIGINT处理程序运行完毕,SIGALRM处理程序才运行

#include <stdio.h>     /* standard I/O functions                         */
#include <stdlib.h>    /* exit                                           */
#include <unistd.h>    /* standard unix functions, like getpid()         */
#include <signal.h>    /* signal name macros, and the signal() prototype */

/* first, define the Ctrl-C counter, initialize it with zero. */
int ctrl_c_count = 0;
int got_response = 0;
#define CTRL_C_THRESHOLD  5 

/* the Ctrl-C signal handler */
void catch_int(int sig_num)
{
  /* increase count, and check if threshold was reached */
  ctrl_c_count++;
  if (ctrl_c_count >= CTRL_C_THRESHOLD) {
    char answer[30];

    got_response = 0;
    alarm(5);

    /* prompt the user to tell us if to really
     * exit or not */
    printf("\nReally exit? [Y/n]: ");
    fflush(stdout);

    fgets(answer, sizeof(answer), stdin);
    if (answer[0] == 'n' || answer[0] == 'N') {
      printf("\nContinuing\n");
      fflush(stdout);
      /* 
       * Reset Ctrl-C counter
       */
      ctrl_c_count = 0;
      got_response = 1;
    }
    else {
      printf("\nExiting...\n");
      fflush(stdout);
      exit(0);
    }
  }
}

/* the SIGALRM signal handler */
void catch_alrm(int sig_num)
{
  printf("\nGot to alarm handler\n");
  if (got_response == 0)
  {
    printf("User taking too long to respond. Exiting ...\n");
    exit(0);
  }
}

int main(int argc, char* argv[])
{
  struct sigaction sa;
  sigset_t mask_set;  /* used to set a signal masking set. */

  /* setup mask_set */
  sigfillset(&mask_set);

  sigdelset(&mask_set, SIGALRM);

  /* set signal handlers */
  // set up the signal handler for Ctrl-C (SIGINT)
  sa.sa_handler = catch_int;
  sigaction(SIGINT, &sa, NULL);

  // set up signal handler for alarm (SIGALRM)
  sa.sa_handler = catch_alrm;
  sigaction(SIGALRM, &sa, NULL);

  while(1)
  {
    pause(); 
  }

  return 0;
}
#包括/*标准I/O功能*/
#包括/*退出*/
#包括/*标准unix函数,如getpid()*/
#包括/*信号名宏和signal()原型*/
/*首先,定义Ctrl-C计数器,并将其初始化为零*/
int ctrl_c_count=0;
int-got_响应=0;
#定义CTRL\u C\u阈值5
/*Ctrl-C信号处理程序*/
无效捕获整数(整数符号数)
{
/*增加计数,并检查是否达到阈值*/
ctrl_c_count++;
如果(ctrl\u c\u计数>=ctrl\u c\u阈值){
答案[30];
got_response=0;
警报(5);
/*提示用户告诉我们是否要
*是否退出*/
printf(“\n是否真正退出?[Y/n]:”);
fflush(stdout);
fgets(答案、尺寸(答案)、标准尺寸);
如果(回答[0]='n'| |回答[0]='n'){
printf(“\n继续\n”);
fflush(stdout);
/* 
*重置Ctrl-C计数器
*/
ctrl\u c\u计数=0;
got_response=1;
}
否则{
printf(“\nxiting…\n”);
fflush(stdout);
出口(0);
}
}
}
/*SIGALRM信号处理程序*/
无效捕获数(整数符号数)
{
printf(“\n转到报警处理程序\n”);
if(got_response==0)
{
printf(“用户响应时间过长。正在退出…\n”);
出口(0);
}
}
int main(int argc,char*argv[])
{
struct-sigaction-sa;
sigset_u t mask_set;/*用于设置信号屏蔽集*/
/*设置掩码集*/
sigfillset(&mask_set);
sigdelset(&mask_set,SIGALRM);
/*设置信号处理程序*/
//设置Ctrl-C(SIGINT)的信号处理程序
sa.sa_handler=catch_int;
sigation(SIGINT,&sa,NULL);
//设置报警信号处理器(SIGALRM)
sa.sa_handler=catch_alrm;
sigaction(SIGALRM,&sa,NULL);
而(1)
{
暂停();
}
返回0;
}
有人能告诉我为什么SIGALRM处理程序在SIGINT处理程序完成之前不运行吗?我知道我可能不应该从信号处理程序内部打印东西,但正如我所说的,这是针对类的,我被告知只能这样做


感谢您的任何帮助

信号处理程序应该很短,并且不做任何可以停止进程的事情。例如,您不能停止输入。而且
printf
不是信号安全功能。您需要后退一步,阅读更多关于信号和信号处理的内容。并重新考虑您的设计(或者更确切地说是您的实现)。还要注意,某些信号会阻止其他信号。我知道printf不是一个信号安全函数,但我不允许更改此实现,因为它是用于类的。我所能做的就是为SIGALRM创建一个处理程序,并从SIGINT处理程序内部调用alarm。您的老师是否为
SIGINT
处理程序提供了代码?然后你真的应该叫老师,因为他用了一个非常糟糕的例子。是的,我得到了SIGINT处理程序和主函数的代码。我可以和教授谈谈,但我真的认为这不会有多大改变。即使我通过
sigdelset
将其他信号解除屏蔽,SIGINT是否也会阻止它们被检测到?SIGALRM的处理程序直到SIGINT处理程序运行完毕才运行。出于某种原因,信号处理程序应该很短,并且不执行任何可能停止进程的操作。例如,您不能停止输入。而且
printf
不是信号安全功能。您需要后退一步,阅读更多关于信号和信号处理的内容。并重新考虑您的设计(或者更确切地说是您的实现)。还要注意,某些信号会阻止其他信号。我知道printf不是一个信号安全函数,但我不允许更改此实现,因为它是用于类的。我所能做的就是为SIGALRM创建一个处理程序,并从SIGINT处理程序内部调用alarm。您的老师是否为
SIGINT
处理程序提供了代码?然后你真的应该叫老师,因为他用了一个非常糟糕的例子。是的,我得到了SIGINT处理程序和主函数的代码。我可以和教授谈谈,但我真的认为这不会有多大改变。即使我通过
sigdelset
将其他信号解除屏蔽,SIGINT是否也会阻止它们被检测到?而SIGALRM的处理程序只是在SIGINT处理程序由于某种原因运行完毕之后才会运行