【问题标题】:SIGINT singal is being catched only onceSIGINT 信号仅被捕获一次
【发布时间】:2017-05-31 15:21:36
【问题描述】:

这里是这个问题的简单重现:

void handler(int sig){
        if(sig == SIGINT){
                printf("Signal caught\n");
                execl("./recreate","./recreate",NULL);
        }
}

int main(){
    printf("Main start\n");
    signal(SIGINT,handler);
    while(1);

        return 0;
}

它只是在收到信号后再次运行。发生的情况是它只能从终端读取 CTR+C 一次。从第二点开始,只需在控制台上写入 ^C 即可。我是否需要每次都重置处理程序或类似的东西?提前致谢。

【问题讨论】:

  • signal 的行为取决于您拥有的 Unix 变体。要获得一致的行为,请改用sigaction
  • 有很好的一般信号处理文档,特别是 signal() 函数可以在线获取,也可以通过 man 命令获取。
  • 另请注意,printf 不被认为是在信号处理程序中调用的安全函数。

标签: c unix signals sigint


【解决方案1】:

signal 是高度实现定义的,因此您应该使用sigaction。您正在观察的是signal 的所谓 sysv 语义——信号在处理程序中被重置为 SIG_DFL 并且它没有被阻止重新执行。

你可能想要这样的东西:

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

#define WRITE_LIT(fd, lit) write(fd, lit, sizeof lit - 1)

void handler(int sig){
        if(sig == SIGINT){
            WRITE_LIT(2, "Signal caught\n");
            execl("./recreate","./recreate", (char*)NULL);
            WRITE_LIT(2, "Couldn't run ./recreate\n");
            _exit(127);
        }
}

int main(){
    printf("Main start\n");
    sigaction(SIGINT, &(struct sigaction const){ 
        .sa_handler = handler, 
        .sa_flags = SA_NODEFER /*don't block signals for the new process image*/
    },
    0);
    while(1);
        return 0;
}

这不会重置信号,也不会阻塞它(默认是在处理程序期间阻塞它),因为新的进程映像可能不希望它阻塞。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-05
    • 2015-01-28
    • 1970-01-01
    • 1970-01-01
    • 2021-03-24
    相关资源
    最近更新 更多