我正在写一个debugging utility,我希望fork
一个孩子,同时阻止孩子终止触发SIGCHLD
到其父级。我仍然希望其他孩子在终止时通常会导致SIGCHLD
。
我想这样做是因为我不希望fork
触发现有的$SIG{CHLD}
处理程序,但我仍然希望其他孩子触发它。也就是说,我想隔离我的新生儿,我不希望它干扰现有儿童的管理。
我担心本地安装自定义$SIG{CHLD}
处理程序,因为我认为我无法正确检测何时应该调用原始处理程序。例如,如果我安装了一个本地$SIG{CHLD}
处理程序,那么一旦我生成一个孩子并让父SIGCHLD
终止它,我肯定会收到一个waitpid
信号。但是,SIGCHLD
不会表明其他孩子是否已经终止,所以我无法确定是否要调用原始处理程序。
我研究过一个进程不能改变它的父pid。我不确定更改子进程组ID或会话ID是否有用。
是否可以阻止特定的孩子触发父母的SIGCHLD
?当我收到一个它没想到的孩子的$SIG{CHLD}
信号时,我是否被迫依靠现有的SIGCHLD
处理程序做正确的事情?
虽然可能有更好的方法来实现调试实用程序(让我知道是否有),我仍然想知道POSIX是否提供对孩子的这种细粒度控制,并且我正在寻找Perl解决方案来解决我的困境
答案 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;
}