父进程定时器回调函数中fork,子进程execl,为什么子进程无法接收到SIGALRM信号?

新手上路,请多包涵

父进程定时器回调函数中fork,子进程execl,子进程无法接收到SIGALRM信号

父进程代码

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

int execTime = 0;
void signalFunc()
{
  printf("test_time\n");
  if (!execTime++)
  {
    int pid = fork();
    if (!pid)
    {
      alarm(0);
      execl("/home/fic091/code/test_child", "/home/fic091/code/test_child", NULL);
    }
  }
  alarm(10);
}

int main()
{
  printf("father pid: %d\n", getpid());
  signal(SIGALRM, signalFunc);
  alarm(2);
  while(1)
  {
    pause();
  }
  return 0;
}

子进程代码

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

int execTime = 0;
void signalFunc()
{
  printf("test_child\n");
  
  alarm(2);
}

int main()
{
  printf("child pid: %d\n", getpid());
  signal(SIGALRM, signalFunc);
  alarm(10);
  while(1)
  {
    //   sleep(2);
    //   signalFunc();
    pause();
  }
  return 0;
}

子进程一直pause,通过命令行kill发送SIGALRM信号,STRACE监控,子进程没有接收到信号

阅读 1.2k
avatarAI BotBETA

在你的程序中,子进程无法接收到SIGALRM信号的主要原因是与UNIX/Linux的信号处理和进程隔离机制有关。当你从父进程的定时器回调函数中调用fork()创建一个子进程时,子进程会继承父进程的各种状态,包括信号处理设置(handler),但是关于信号的阻塞状态(blocked signals)和挂起信号(pending signals)则遵循不同的规则。

具体来说,子进程继承父进程的信号处理器(signal handler),但不会继承父进程的挂起信号(即那些在父进程中已经发出但尚未处理的信号)。SIGALRM信号是在父进程中发出的,用于触发定时器回调,并且在该回调函数中调用了fork()。在fork()调用时,父进程中的SIGALRM信号已经是挂起状态(如果回调在信号到来时已经被触发),但这个挂起状态不会被传递给子进程。

因此,即使子进程设置了与SIGALRM相关联的信号处理器,由于该信号没有在子进程中挂起,子进程永远不会因为这个信号而被唤醒。当你通过命令行使用kill命令向子进程发送SIGALRM信号时,如果子进程已经正确设置了信号处理器,那么它会收到并处理这个信号。

解决或验证的方法

  1. 使用kill命令手动发送信号:如你所做的,使用kill -SIGALRM <子进程PID>来测试子进程是否能响应SIGALRM信号。这应该能看到子进程的处理函数被调用。
  2. 在子进程中验证信号处理器设置:你可以在子进程的main函数开始时,添加一些代码来确认信号处理器确实已经被设置。
  3. 监控和调试:使用工具如stracegdb来跟踪信号处理和fork()调用的行为。
  4. 文档和阅读:深入阅读关于UNIX/Linux信号处理和进程控制的文档,了解信号的行为和父子进程间的交互。

最后,如果你的目标是让子进程定时执行某些操作,你可能需要重新考虑设计,因为基于信号和fork()的组合可能会导致复杂的同步和竞态条件问题。你可以考虑使用其他同步机制(如管道、消息队列、条件变量等)或者使用专门的定时器API(如POSIX定时器)来简化你的程序。

1 个回答
✓ 已被采纳新手上路,请多包涵

父进程在SIGALRM回调函数中屏蔽了SIGALRM信号,子进程fork时继承了屏蔽,所以需要取消对SIGALRM信号的阻塞

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进