Override Ctrl-C

Override Ctrl-C

本文关键字:Ctrl-C Override      更新时间:2023-10-16

我应该覆盖CtrlC信号并使用它来打印消息。它不应该结束程序。

到目前为止发生的事情是,当按下CtrlC时,它打印消息,但结束程序。

当我问我的教授时,他告诉我这样做:您需要使信号处理程序停止继续处理该信号。现在你的代码正在处理这个信号,然后再传递给父处理程序。

是否有一种方法,我应该添加或我需要移动信号安装的地方?

这是我到目前为止的代码:

#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>  
#include <sys/types.h>
#include <signal.h> 
#include "Input.h"
#include "CircleBuff.h"
//void handler_function(int signal_id);
void catch_int(int sig_num){
    //reset the signal handler again to catch_int, for next time
    signal(SIGINT, catch_int);
    //print message
    printf("Print History");
    fflush(stdout);
}
void printHistory(CircleBuff hist){
    cout << "Complete History:n" << endl;
    hist.print();
    cout << endl;
}
int main(int argc, char** argv){
  struct sigaction signal_action;                /* define table */
  signal_action.sa_handler = catch_int;   /* insert handler function */
  signal_action.sa_flags = 0;                    /* init the flags field */
  sigemptyset( &signal_action.sa_mask );     /* are no masked interrupts */
  sigaction( SIGINT, &signal_action, NULL ); /* install the signal_action */
  do{

  //My code: where the value report will be assigned within.
  } while(report != 1)
}

哇,方式太多的代码筛选。然而,如果你使用C标准库,你应该得到想要的行为。下面是c++版本:

#include <iostream>
#include <csignal>
sig_atomic_t sigflag = 0;
void sighandler(int s)
{
  // std::cerr << "Caught signal " << s << ".n"; // this is undefined behaviour
  sigflag = 1; // something like that
}
int main()
{
  std::signal(SIGINT, sighandler);
  // ... your program here ...
  // example: baby's first loop (Ctrl-D to end)
  char c;
  while (std::cin >> c)
  {
    if (sigflag != 0) { std::cerr << "Signal!n"; sigflag = 0; }
  }
}

这将捕获Ctrl-C(引发SIGINT),并且不替换信号处理程序,因此它每次都会触发,并且没有人终止程序。

注意,信号处理程序是由fork() ed的子代继承的。

Posix函数sigaction()允许您注册"一次性"处理程序,这些处理程序在调用一次后被标准处理程序替换。这是更高级的和特定于posix的。

Edit:正如@Dietrich指出的,你不应该在信号处理程序中做任何真正的工作。相反,您应该设置一个标志(我提供了一个示例),并在循环中检查该标志(并在那里打印消息)。我也会修改这个例子

您是否考虑过在while循环中可能存在'EINTR'失败的可中断函数。您可以通过使用:

来修复它。
sa.sa_flags = SA_RESTART;

或者,只检查errno并循环。你确定这个程序还没到终止的时候吗。