首页 > 解决方案 > 进程在 SIGINT 信号后死亡

问题描述

我不明白这里发生了什么,我有一个父进程处理 SIGINT 信号然后生成一个子进程。当我按下Ctrl+时,我期望C两个进程都会打印“收到 SIGINT”,然后继续,但事实证明,父进程在收到 SIGINT 后死亡,但子进程仍然存在。我无法理解。

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

void handler (int sig) {
  printf("SIGINT received\n");
}

void child() {
  while (1) {
    printf("I'm the child\n");
    sleep(1);
  }

  exit(0);
}

int main(int argc, char *argv[]) {
  struct sigaction act;

  memset(&act, 0, sizeof(act));

  act.sa_handler = &handler;
  // Link SIGINT with the handler
  sigaction(SIGINT, &act, NULL);

  // Create child
  if (fork() == 0) child();

  wait(NULL);

  return 0;
}

执行示例:

$ ./test_signals
I'm the child
^CSIGINT received
I'm the child
SIGINT received
$ I'm the child
I'm the child

所以两个进程都处理 SIGINT 但父进程在子进程继续时死亡......

标签: clinuxsignalsposix

解决方案


父进程在主函数中被阻塞,并在接收到信号后处理它并从调用返回并返回wait错误。

孩子只是在while处理 SIGINT 中循环。当处理的代码返回到它原来的位置(可能在睡眠中被阻塞)并继续循环。

该代码可能说明会发生什么:

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

void handler (int sig) {
  printf("SIGINT received %d\n",getpid());
}

void child() {
  while (1) {
    printf("I'm the child\n");
    sleep(1);
  }

  exit(0);
}

int main(int argc, char *argv[]) {
  struct sigaction act;

  memset(&act, 0, sizeof(act));

  act.sa_handler = &handler;
  // Link SIGINT with the handler
  sigaction(SIGINT, &act, NULL);

  // Create child
  if (fork() == 0) child();

  int r = wait(NULL);
  if (r==-1 && errno==EINTR) printf("signal probably received in parent\n");

  return 0;
}

请注意,printf禁止调用信号处理程序。


推荐阅读