SIGCHLD导致分段错误,不会进入处理程序

时间:2014-11-11 17:22:45

标签: c shell signals

我正在尝试创建一个简单的shell并添加功能以在后台使用&运行进程。 在我的主要方法中,我基本上有:

int main() {
  if (signal(SIGCHLD, handle) == SIG_ERR)
    perror("Cannot catch SIGCHLD");
  pid_t child = fork();
  if (child == 0)
    execvp(command, arguments);
  else {
    if (background == 1) {
       printf("1");
       backgroundList(command, child);
       printf("2"); }
    else 
      waitpid(child, NULL, 0);
  }
}

对于我的经纪人,我有:

void handle(int s) {
  printf("a");
  if (signal(SIGCHLD, handle) == SIG_ERR)
    perror("Cannot catch SIGCHLD");
  pid_t pid;
  printf("b");
  while((pid = waitpid(0, NULL, WNOHANG)) > 0) {
    printf("c");
    rmBackgroundList(pid);
    printf("d");
  }
}

我可以让它在前台运行一个进程就好了。运行“ls”将内容打印到屏幕上,然后打印“a”和“b”,因为它进入SIGCHLD处理程序,但它不会转到“c”,因为它已经等待了。

但是,在后台运行某些内容(“ls&”)将打印“1”和“2”,让父母返回提示,然后孩子将内容打印到屏幕,然后分段错误。它不会打印处理程序中的任何字母。

我无法弄清楚为什么SIGCHLD对已经等待但却导致分段错误的孩子有好处,甚至从未进入处理器以处理未等待的进程。

1 个答案:

答案 0 :(得分:0)

您没有遵循信号处理程序的规则。您无法使用printf()perror()Read the rules on what is safe to do in a signal handler.

signal()的行为也会发生变化,具体取决于它是否是BSD或SysV样式的Unix。 Linux根据_BSD_SOURCE或_GNU_SOURCE的存在更改其在glibc中的行为,并且根据您是否调用gcc -ansigcc -std=c99gcc -std=gnu99

而更改

您应该使用sigaction()代替signal()