c - 为什么信号处理出现故障?

标签 c linux bsd signal-handling

我有一个信号处理片段,但它在我的 Mac 和虚拟 Linux 机器上出现故障 koding.com但在我的办公室 Linux PC 上它正在工作..有人可以告诉我为什么..

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

void my_isr(int n){
   printf("Hello World");
   signal(SIGINT, SIG_DFL);

}


int main(){
   signal(SIGINT, my_isr);
   printf("pid = %d\n", getpid());
   while(1);

   return 0;
 }

当我按下 Ctrl+C 时,它不是第一次打印 Hello World,而是重新修改 SIGINT 信号操作,因此它正在退出当我第二次按 Ctrl+C 时程序。谁能解释一下为什么?

最佳答案

您不能调用信号处理程序中的每个函数。

阅读signal(7) . 只有异步信号安全函数可以被调用(直接或间接)来自信号处理程序,而printf不是这样的功能。如果你真的想从信号处理程序中可靠地“打印”一些东西(我不推荐),你只能使用低级 write(2)系统调用(它是异步信号安全的)。

所以你有 undefined behavior . This解释了为什么它如此糟糕

推荐的方法是在你的信号处理程序中设置一个volatile sigatomic_t 标志,并在它的之外测试它(例如在你的while 循环...)。 你忘了打电话fflush(3) .您可能更幸运地以 \n 结束您的 printf 格式字符串,因为 stdout 是行缓冲的!

当然,在信号处理程序中更改 printf 仍然是 UB,即使使用 \n,但通常它似乎可以工作。

这是您程序的符合标准的版本....

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

volatile sig_atomic_t got_signal;

void my_sigint_handler (int signum) {
  if (signum == SIGINT) // this is always true!
    got_signal = 1;
#define INTERRUPT_MESSAGE "Interrupted!\n"
  write(STDOUT_FILENO, INTERRUPT_MESSAGE, strlen(INTERRUPT_MESSAGE));
};

int main(int argc, char**argv) {
  struct sigaction act_int;
  memset (&act_int, 0, sizeof(act_int));
  act_int.sa_handler = my_sigint_handler;
  if (sigaction(SIGINT, &act_int, NULL)) {
     perror("sigaction"); exit(EXIT_FAILURE);
  };
  printf ("start %s pid %d\n", argv[0], (int)getpid());
  while (!got_signal) {
  };
  printf ("ended %s after signal\n", argv[0]);
  return 0;
}

一个有用的(也是允许的)技巧可能是 write(2) pipe(7) 上的单个字节 - 在你的信号处理程序中到自己(你在程序初始化的早期使用 pipe(2) 设置该管道),并在你的事件循环中 poll(2)该管道的读取端。

关于c - 为什么信号处理出现故障?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31588736/

相关文章:

python - 如何在Linux上正确安装python?

ios - 我如何知道 *.a 文件是为哪个架构构建的?

c - 释放链表时堆栈溢出 : Segmentation fault after 100k nodes successfully freed

c - strrev()的返回值有什么用?

c - 从 C 中的原始图像获取每个像素的 RGB 值

r - 加载共享库时出错 : libicuuc. so.50

linux - 编译lirc-redrat3-0.8.7时出错

缓存友好矩阵移位函数

C++ - Fedora 12 上的 GCC4.4.4 缺少 STL_alloc.h?

c - 为什么sys/queue.h中的双向链表会维护previous next元素的地址?