5

我正在编写一个调试实用程序,并且我想要fork一个孩子,同时防止该孩子的终止触发SIGCHLD其父母。我仍然希望其他孩子通常会SIGCHLD在终止时引起 a。

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

我对在本地安装自定义$SIG{CHLD}处理程序持谨慎态度,因为我认为我无法正确检测何时应该调用原始处理程序。例如,如果我安装了一个本地处理程序,那么一旦我产生一个孩子并让父母终止它,$SIG{CHLD}我就可以保证收到一个信号。但是,这并不能表明其他孩子是否也终止了,所以我不能确定是否调用原始处理程序。SIGCHLDwaitpidSIGCHLD

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

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

尽管可能有更好的方法来实现该调试实用程序(如果有,请告诉我),但我仍然想知道 POSIX 是否提供对儿童的如此细粒度的控制,并且正在寻找一种 Perl 解决方案来解决我的困境。

4

2 回答 2

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();
}
于 2014-03-05T16:30:29.577 回答
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;
}
于 2014-03-05T16:04:24.440 回答