接收到信号后,子进程仍然无法运行

时间:2016-03-30 13:33:21

标签: c linux signals

代码是this question的答案之一。

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


void
sigusr1( int pidno )
{
  fprintf(stderr, "Caught\n");
}

int
main()
{
  pid_t pid;

  signal( SIGINT, sigusr1 );
  if( (pid = fork()) == 0 ){
    pause();
    fprintf(stderr, "Child\n");
  }
  else
  {
    fprintf(stderr, "Parent\n");
    kill( pid , SIGINT ); //parent sends signal to child
  }
  pause();
  return 0;
}

孩子等待信号,收到信号后继续执行。

运行它我得

Parent
Caught

似乎孩子在收到信号后没有跑步。按Ctrl + c:

Parent
Caught
^CCaught
Caught
Child

有人能解释一下这里发生了什么吗?

1 个答案:

答案 0 :(得分:2)

在信号被孩子接收和处理后,

pause()被调用。不幸的是,pause() easily introduces this kind of race condition

time you parent                   child
---- --- ------                   -----
  0      signal(SIGINT,handler)
  1      fork()                   (hello)
  2      print("Parent")          (waking up)
  3      kill(..., SIGINT)        <<SIGINT>>               # RACE kill v pause
  4                               handler: print("Caught")
  5      pause()                  pause()
  6   ^C <<SIGINT>>               <<SIGINT>>
  7      handler: print("Caught") handler: print("Caught")
  8      exit                     pause()
  9                               (still running)

要检查究竟是什么,请尝试将%i,getpid()添加到printfs,也可以在子分支中的pause()调用之前再添加一个printf()。

sigsuspend()显式信号屏蔽可能是更好的选择。