【问题标题】:Cannot change default action for SIGINT无法更改 SIGINT 的默认操作
【发布时间】:2017-03-17 08:57:15
【问题描述】:

在 C 中,我想捕捉 SIGINT 信号并打印出一条消息,例如 通过使用 sigaction 并将新的处理程序传递给它来“收到 SIGINT”

sa.sa_sigaction = handler;

我不想终止程序。

如果我通过 shell 运行我的程序并使用 Ctrl+c 生成信号,信号处理程序将捕获信号并打印出我的消息。

之后,它将执行终止进程的默认操作。

我做错了什么?

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <string.h>
#include <signal.h>

static void handler(int sig, siginfo_t* si, void *unused){
    if(sig == SIGINT){
        printf("Signal %i received\n",si->si_signo);
    }
}

int main(int argc, char* argv[]){
    char s [256];


    struct sigaction sa;

    sigemptyset(&sa.sa_mask);
    sigaddset(&sa.sa_mask, SIGINT);
    sa.sa_flags = SA_SIGINFO;
    sa.sa_sigaction = handler;

    if(sigaction(SIGINT, &sa, NULL) < 0 ){
        perror("sigaction");
    }

    fgets(s,sizeof(s), stdin);
    printf("%s", s);
    return 0;
}

【问题讨论】:

  • 在sigaction之后,从main返回之前你会做什么?
  • 我已经更新了代码。我只是回应用户输入。
  • 那么你怎么知道 sigint 会终止你的程序呢?我认为它刚刚结束,因为 fgets 返回。
  • 当我按下 Ctrl+C 时,我会收到“收到信号 2”的消息。根据signal(7)的手册,2代表SIGINT。 1)我清空信号掩码,这意味着不应该阻塞任何信号。 2)我将 SIGINT 添加到信号掩码中,这意味着“阻止此信号”......但删除该行也无济于事。 3) 我将自己的处理程序传递给 sa.sa_sigaction。
  • 问题是SIGINT不仅会导致handler被调用,还会导致read调用被中断并返回错误,请看下面我的回答。

标签: c linux signals sigint sigaction


【解决方案1】:

问题是fgets会调用read系统调用,而系统调用在被SIGINT打断时会返回错误,请看man page of read:

EINTR 在读取任何数据之前调用被信号中断;见信号(7)。

因此,您应该检查fgetserrno,如果是EINTR,请继续致电fgets。试试我更新的程序:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <string.h>
#include <signal.h>
#include <errno.h>

static void handler(int sig, siginfo_t* si, void *unused){
    if(sig == SIGINT){
        printf("Signal %i received\n",si->si_signo);
    }
}

int main(int argc, char* argv[]){
    char s [256];


    struct sigaction sa = {0};

    sigemptyset(&sa.sa_mask);
    sigaddset(&sa.sa_mask, SIGINT);
    sa.sa_flags = SA_SIGINFO;
    sa.sa_sigaction = handler;

    if(sigaction(SIGINT, &sa, NULL) < 0 ){
        perror("sigaction");
    }

    char *p;
    do {
        p = fgets(s,sizeof(s), stdin);
    } while (!p && errno == EINTR);
    printf("%s\n", s);
    return 0;
}

【讨论】:

  • 你说得对......我忘记了 read 系统调用......我只是用无限循环(wihle(1))试过它,它工作......谢谢很多!
猜你喜欢
  • 2021-10-07
  • 2015-04-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-08-26
  • 2015-11-09
  • 1970-01-01
相关资源
最近更新 更多