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



我有一个信号处理片段,但它在我的Mac和koding.com的虚拟Linux盒上不知何故出现故障,但在我的办公室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 = %dn", getpid());
   while(1);
   return 0;
 }

当我按Ctrl+C时,它不是第一次打印Hello World,而是重新修改SIGINT信号动作&因此,当我第二次按Ctrl+C时,它正在退出程序。有人能告诉我为什么吗?

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

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

所以你有未定义行为。这就解释了为什么这么糟糕

建议的方法是在信号处理程序中设置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 %dn", argv[0], (int)getpid());
  while (!got_signal) {
  };
  printf ("ended %s after signaln", argv[0]);
  return 0;
}

一个有用的(并且允许的)技巧可以是在管道(7)上写(2)一个单字节-在你的信号处理程序中-到self(你在程序初始化时使用pipe(2)设置该管道),并在事件循环poll(2)中该管道的读端。

printf是罪魁祸首,只要在处理程序中使用counter并在处理程序外部打印其值就可以了。

使用sigaction代替signal

相关内容

  • 没有找到相关文章

最新更新