在perl中,使用open创建child时会杀死child及其子 [英] In perl, killing child and its children when child was created using open
问题描述
这是我的代码,为清楚起见删除了错误处理和其他内容:
Here's my code, with error handling and other stuff removed for clarity:
sub launch_and_monitor {
my ($script, $timeout) = @_;
sub REAPER {
while ((my $child = waitpid(-1, &WNOHANG)) > 0) {}
$SIG{CHLD} = \&REAPER;
}
$SIG{CHLD} = \&REAPER;
my $pid = fork;
if (defined $pid) {
if ($pid == 0) {
# in child
monitor($timeout);
}
else {
launch($script);
}
}
}
launch子执行一个shell脚本,该脚本随后又启动其他进程,例如:
The launch sub executes a shell script which in turn launches other processes, like so:
sub launch($) {
my ($script) = @_;
my $pid = open(PIPE, "$script|");
# write pid to pidfile
if ($pid != 0) {
while(<PIPE>) {
# do stuff with output
}
close(PIPE) or die $!;
}
}
Monitor子程序基本上只是等待指定的时间,然后尝试杀死Shell脚本.
The monitor sub basically just waits for a specified period of time and then attempts to kill the shell script.
sub monitor($) {
my ($timeout) = @_;
sleep $timeout;
# check if script is still running and if so get pid from pidfile
if (...) {
my $pid = getpid(...);
kill 9, $pid;
}
}
这会杀死脚本,但是不会杀死它的任何子进程.如何解决?
This kills the script, however, it does not kill any of it's sub processes. How to fix?
推荐答案
如果操作系统支持进程组,则可以执行此操作.您需要使脚本流程成为流程组负责人.它运行的子进程将从其父进程继承该进程组.然后,您可以使用kill将信号同时发送到组中的每个进程.
You can do this with process groups, if your operating system supports them. You need to make the script process become a process group leader. The child processes that it runs will inherit the process group from their parent. You can then use kill to send a signal to each process in the group at the same time.
在launch()
中,您需要将open
行替换为分叉的行.然后在子级中,您将在执行命令之前调用setpgrp()
.像下面这样的东西应该起作用:
In launch()
, you will need to replace the open
line with one that forks. Then in the child, you would call setpgrp()
before exec'ing the command. Something like the following should work:
my $pid = open(PIPE, "-|");
if (0 == $pid) {
setpgrp(0, 0);
exec $script;
die "exec failed: $!\n";
}
else {
while(<PIPE>) {
# do stuff with output
}
close(PIPE) or die $!;
}
稍后,要杀死脚本进程及其子进程,请取消您要发信号通知的进程ID:
Later, to kill the script process and its children, negate the process ID that you're signalling:
kill 9, -$pid;
这篇关于在perl中,使用open创建child时会杀死child及其子的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!