2011-10-01 85 views
12

我应该重载CtrlC信号并用它来打印信息。它不应该结束程序。重写Ctrl-C

到目前为止,会发生什么事是,当按CtrlÇ按下它打印的消息,但最终的方案。

当我问我的教授时,他告诉我这样做: 您需要让信号处理程序不要继续处理信号。现在信号正在被您的代码处理,然后继续处理父处理程序。

有没有一种方法,我应该添加或我需要将信号安装程序移到某个地方?

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

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

} 
+0

您不应该在信号处理函数中调用'printf',因为'printf'不是异步安全的。有关异步安全功能的列表,请参见man 7 signal。更简单的'write'系统调用是异步安全的,但是没有一个是''功能。 –

回答

10

哇,方式太多的代码去筛选。但是,如果您使用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()版本的子代继承。

Posix函数sigaction()允许您在被调用一次之后注册由标准处理程序替换的“一次性”处理程序。不过,这是更先进的和Posix特定的。

编辑:作为@Dietrich所指出的,你应该永远不会做任何实际工作的信号处理程序。相反,你应该设置一个标志(我提供了一个例子),并检查你的循环内的标志(并在那里打印消息)。我也会修改这个例子。

+0

在信号处理程序中使用'std :: cerr'是非常不安全的。 –

+0

@DietrichEpp:不安全还是不可预测?最糟糕的情况是什么?当然,正确的做法是设置一个标志并继续前进,但这会让这个例子复杂化。不过,我会记下来的。 –

+0

感谢您的意见。我会尝试这个选项,不幸的是,教授希望我们用c方法处理信号。 (我也缩短了只包含重要内容的代码) – ensantos91

0

你是否认为在while循环中可能会有一个可中断函数与'EINTR'失败。您可能可以通过以下方式修复它:

sa.sa_flags = SA_RESTART; 

或者,只需检查errno并进行循环。你确定该计划没有达到终止的程度。尝试在主要结尾处放置打印语句。