ctrl + c与C中的SIGINT无关

时间:2015-07-30 03:36:24

标签: c linux

我试过这段代码。

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

void sighandler(int);

int main()
{
   signal(SIGINT, &sighandler);

   while(1) 
   {
      sleep(1); 
   }
   return(0);
}

void sighandler(int signum)
{
   printf("Caught signal %d, coming out...\n", signum);
   exit(1);
}

但是当我按下ctrl + c时,它并没有捕捉到信号。但是当我让它在后台运行并使用kill命令发送SIGINT信号时,它正常工作。请帮助我......

2 个答案:

答案 0 :(得分:1)

printfexit在信号处理程序内部调用是不安全的。有关您可以做的有限的事情,请参阅signal(7)

程序出现故障的直接原因可能是stdout的文件缓冲区没有被刷新。

此更改应解决此问题:

void sighandler(int signum)
{
   char msg[] = "Caught signal, coming out...\n";
   write( STDOUT_FILENO, msg, sizeof msg );
   _exit(1); // Do not call atexit routines.
}

然而,更好的策略是避免在处理程序中做任何实际工作。只需设置一个标志并返回。

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

void sighandler(int);
volatile sig_atomic_t gotsig = 0;
volatile sig_atomic_t signum;

int main()
{
   signal(SIGINT, &sighandler);

   while(!gotsig) 
   {
      sleep(1); 
   }
   printf("Caught signal %d, coming out...\n", signum);
   exit(1);
}

void sighandler(int in_signum)
{
    gotsig = 1;
    signum = in_signum;
}

答案 1 :(得分:0)

我记得读过sigaction是首选的功能,而不是signal,这不是便携式的(非常确定它来自The Linux Programming Interface,这是我认为必不可少的参考资料)。

我的第一个想法是,如果系统不符合POSIX,Ctrl + C可能不会发送SIGINT信号,因此我制作了一个测试程序,以查看我可以提出的相关信号。当我尝试这个时,@ Potatoswatter的答案突然出现,它似乎与你不能获得输出的直接问题更相关。无论如何,这是一个POSIX友好的源文件来测试四个信号(SIGINTSIGTERMSIGTSTPSIGQUIT):

#define _POSIX_C_SOURCE 200809L
#include <unistd.h>

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

void sigHandler(int sig);
static int did_catch = 0;
static int sig_caught = 0;

int main() {

    struct sigaction sa;

    /* buidl sigaction struct */
    sa.sa_handler = sigHandler;
    if (sigemptyset(&sa.sa_mask) != 0) { perror("\nsigemptyset"); exit(EXIT_FAILURE); }
    sa.sa_flags = 0;

    /* handle signals */
    if (sigaction(SIGINT, &sa, NULL) != 0) { perror("\nproblem adding SIGINT"); exit(EXIT_FAILURE); }
    if (sigaction(SIGTERM, &sa, NULL) != 0) { perror("\nproblem adding SIGTERM"); exit(EXIT_FAILURE); }
    if (sigaction(SIGQUIT, &sa, NULL) != 0) { perror("\nproblem adding SIGQUIT"); exit(EXIT_FAILURE); }
    if (sigaction(SIGTSTP, &sa, NULL) != 0) { perror("\nproblem adding SIGTSTP"); exit(EXIT_FAILURE); }

    /* wait for signal */
    while (!did_catch) {
        pause();
    }

    /* check caught signals */
    if (sig_caught == SIGINT) printf("\nsignal is SIGINT\n");
    else if (sig_caught == SIGTERM) printf("\nsignal is SIGTERM\n");
    else if (sig_caught == SIGQUIT) printf("\nsignal is SIGQUIT\n");
    else if (sig_caught == SIGTSTP) printf("\nsignal is SIGTSTP\n");
    else printf("\nsignal captured is not listed\n");

    return 0;
}

void sigHandler(int sig) {
    sig_caught = sig;
    did_catch = 1;
}

希望这有帮助。