有没有办法阻止特定的孩子触发SIGCHLD?

时间:2014-03-05 15:05:56

标签: perl fork posix sigchld

我正在写一个debugging utility,我希望fork一个孩子,同时阻止孩子终止触发SIGCHLD到其父级。我仍然希望其他孩子在终止时通常会导致SIGCHLD

我想这样做是因为我不希望fork触发现有的$SIG{CHLD}处理程序,但我仍然希望其他孩子触发它。也就是说,我想隔离我的新生儿,我不希望它干扰现有儿童的管理。

我担心本地安装自定义$SIG{CHLD}处理程序,因为我认为我无法正确检测何时应该调用原始处理程序。例如,如果我安装了一个本地$SIG{CHLD}处理程序,那么一旦我生成一个孩子并让父SIGCHLD终止它,我肯定会收到一个waitpid信号。但是,SIGCHLD不会表明其他孩子是否已经终止,所以我无法确定是否要调用原始处理程序。

我研究过一个进程不能改变它的父pid。我不确定更改子进程组ID或会话ID是否有用。

是否可以阻止特定的孩子触发父母的SIGCHLD?当我收到一个它没想到的孩子的$SIG{CHLD}信号时,我是否被迫依靠现有的SIGCHLD处理程序做正确的事情?

虽然可能有更好的方法来实现调试实用程序(让我知道是否有),我仍然想知道POSIX是否提供对孩子的这种细粒度控制,并且我正在寻找Perl解决方案来解决我的困境

2 个答案:

答案 0 :(得分:2)

您无法移植完全阻止SIGCHLD,但如果信号处理程序写得正确,您可以阻止waitpid返回您的调试工具的pid孤儿吧。

use Signal::Mask;
sub start_background_child {
  local $Signal::Mask{CHLD} = 1;
  my $first = fork;
  croak "fork failed: $!" if not defined $first;
  if ($first) {
    waitpid $first, 0;
    return;
  }

  my $second = fork;
  croak "fork failed: $!" if not defined $second;
  exit if $second;

  your_stuff_here();
}

答案 1 :(得分:1)

我认为你可以守护特殊的孩子 - 两次 - 来切断父子关系。创建流程时,您仍然会收到SIGCHLD - 我不知道您是否可以接受。

sub start_special_child {
    return if fork;     # run rest of this routine in child process
    fork && exit;       # run rest of this routine in grandchild process
                        # the  exit  here triggers SIGCHLD in the parent
    ...                 # now run your special process
    exit;               # exit here does not trigger SIGCHLD
}

另一种方法是跟踪子进程的进程ID,并使用waitpid确定哪个进程触发了SIGCHLD处理程序。

$SIG{CHLD} = \&sigchld_handler;
$pid1 = start_child_process();
$pid2 = start_child_process();
$pid3 = start_child_process();
$pidS = start_special_child_process();

sub sigchld_handler {
    $pid = waitpid -1, WNOHANG;     # use POSIX ':sys_wait_h'
    return if $pid == $pidS;
}