我正在运行一个IRC Bot(Bot::BasicBot),它有两个运行File::Tail的子进程,但是当退出时,它们并没有终止。所以我在退出之前使用Proc::ProcessTable杀死它们,如下所示:
my $parent=$$;
my $proc_table=Proc::ProcessTable->new();
for my $proc (@{$proc_table->table()}) {
kill(15, $proc->pid) if ($proc->ppid == $parent);
}
它可以工作,但我收到以下警告:
14045: !!! Child process PID:14047 reaped:
14045: !!! Child process PID:14048 reaped:
14045: !!! Your program may not be using sig_child() to reap processes.
14045: !!! In extreme cases, your program can force a system reboot
14045: !!! if this resource leakage is not corrected.
我还可以做什么来杀死子进程呢?forked进程是使用Bot::BasicBot中的forkit方法创建的。
示例脚本:
package main;
my $bot = SOMEBOT->new ( server => 'irc.dal.net', channels => ['#anemptychannel'] );
$SIG{'INT'} = 'Handler';
$SIG{'TERM'} = 'Handler';
sub Handler {
$bot->_stop('Leaving.');
}
$bot->run;
package SOMEBOT;
use base qw(Bot::BasicBot);
use File::Tail;
use Proc::ProcessTable;
sub irc_error_state { die if $_[10] =~ /Leaving\./; }
sub help { return; }
sub stop_state {
my $parent=$$;
my $proc_table=Proc::ProcessTable->new();
for my $proc (@{$proc_table->table()}) {
kill(15, $proc->pid) if ($proc->ppid == $parent);
}
die;
}
sub connected {
my $self = shift;
$self->forkit (
run => \&announcer,
body => '/home/somebody/somefile.txt',
channel => '#anemptychannel',
) unless $self->{log1};
$self->{log1} = 1;
$self->forkit (
run => \&announcer,
body => '/home/somebody/anotherfile.txt',
channel => '#anemptychannel',
) unless $self->{log2};
$self->{log2} = 1;
}
sub announcer {
my $announcefile = shift;
my $file=File::Tail->new(name => $announcefile, maxinterval=>5, adjustafter=>7);
while (defined(my $line=$file->read)) { chomp $line; print "$line\n"; }
}
5条答案
按热度按时间qoefvg9y1#
我对您提到的任何模块都不熟悉,但是当我在过去编写forking Perl程序时,通常只需在主父进程中放置下面这行代码:
这样,当子进程退出且父进程获得SIGCHLD信号时,它会自动使用
wait
获取子进程。klh5stk12#
我正在挖掘一个旧的帖子,但我正在寻找这个问题的答案,谷歌搜索把这个作为首要结果。所以,为了防止其他人在这个问题上绊倒,这里是我是如何做到的。
在分叉之前,设置一个
pipe
,以便分叉的进程可以进行通信:pipe PARENTRECEIVE,CHILDSEND;
分叉你的进程,让子进程不断地向父进程发送它的新进程ID,然后当你认为子进程挂起时(通过计时器或SIG),你可以杀死子进程:
有时候我们的Web服务器会挂起,所以我用它来检查它是否在合理的时间内仍然响应HTTP GET请求。如果子进程没有在父进程的计时器超时之前完成获取URL,它会发送一封电子邮件警告说发生了什么事情。
ne5o7dgx3#
在“正常”情况下,父进程不应该做任何事情(如果您关心结果,可能调用
waitpid
,或者暂停处理直到它们完成)。这还不是一个真正的答案--您可能需要将一些代码粘贴到子进程中。但是有一点建议--从手动调用
fork
的简单程序开始,而不是依赖CPAN模块来为您完成。了解系统如何处理多个进程是很重要的。当您了解了这些之后,您可以利用一些框架来处理大量流程。如果您最近还没有通读perldoc perlfork,您可能还应该通读一下,并尝试其中的一些示例。
7vux5j2d4#
从0.82版开始,
Bot::BasicBot
会在退出时终止未完成的子进程(由forkit()
创建)。tjvv9vkg5#
Fork将返回父块中子进程的进程ID。
作为对Mintx的答复,不需要管道。