信号接收器在一个文件中(C)

时间:2017-11-26 10:49:04

标签: c signals

我有一项任务 - 检查我是否可以编写一个接收所有信号的程序。我知道我不能,但是当我想写一个程序时,它不能正常工作。可以使用fork()在一个.c文件中完成吗?尽管"Unknown signal 32"

,目前还没有任何内容写入stdout
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>

void signalReceiver(int number) { 
  printf("There it is - %d\n", number);
}

int main(void) {
  int mypid = getpid();

  for(int i = 1; i <= 64; ++i) { 
      signal(i, signalReceiver);
  }   


  int pid = fork();

  if(pid == 0) {

        for(int i = 1; i <= 64; ++i) { 
        //SKIP the signals which interrupt the state of the program
          if( i != 9 && i != 19) {
            kill(mypid, i);
          }
        }
  } else {
    wait(NULL);
  }

getchar();
return 0; }

1 个答案:

答案 0 :(得分:3)

虽然操作系统不允许您注册SIGKILL(9)和SIGSTOP(19)的处理程序,但您的libc不会让您注册保留信号32的处理程序和33(这些用于实现多线程)。

简单的错误检查会检测到这一点:

  if(SIG_ERR==signal(i, signalReceiver))
  { fprintf(stderr, "no sighandler for %d: %m\n", i); }

稍后在输出中:

no sighandler for 9: Invalid argument
no sighandler for 19: Invalid argument
no sighandler for 32: Invalid argument
no sighandler for 33: Invalid argument

现在你得到32以下的信号,但是在处理程序设法输出输出之前32会设法杀死你的父进程(BTW,printf在信号处理程序中使用是不安全的 - 你应该sprintf到缓冲区并直接write。您收到的Unknown signal 32消息来自您的shell,该shell检测到其子节点已被信号32终止。

如果你将杀戮空间化(例如,使用usleep(1000)以便处理程序有机会完成)或者如果你在同一个过程中运行杀戮,那么你应该能够获得32以下信号的消息(在在kill函数返回之前,每个处理程序将完成的情况。

如果您希望该进程存活,请不要发送它未成功注册处理程序的信号。

此外,waitgetchar无法保证不间断通过信号收据。您应该已准备好重新启动wait,例如:

again: if(0>wait(NULL))
if(EINTR==errno) goto again; else perror("wait");

完整修改后的来源:

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

void signalReceiver(int number) { 
    char buf[256] = {0};
    sprintf(buf, "There it is - %d\n", number);
    write(1,buf,strlen(buf));
}

int main(void) {
  int mypid = getpid();

  for(int i = 1; i <= 64; ++i) { 
      if(SIG_ERR==signal(i, signalReceiver))
      { fprintf(stderr, "no sighandler for %d: %m\n", i); }
  }   

  int pid = fork();
  if(0>pid){ perror("fork"); exit(1); }

  if(pid == 0) {

      for(int i = 1; i <= 64; ++i) { 
          //SKIP the signals which interrupt the state of the program
          if( i != 9 && i != 19 && i!=32 && i!=33) {
              kill(mypid, i);
          }
      }
      _exit(0);
  } else {
      again: if(0>wait(NULL))
      if(EINTR==errno) goto again; else perror("wait");
  }

  return 0; 
}