Tôi đang chạy một Bot IRC (Bot::BasicBot) có hai quy trình con chạy File::Tail nhưng khi thoát, chúng không chấm dứt. Vì vậy, tôi killling chúng bằng cách sử Proc::ProcessTable như thế này trước khi thoát:Cách nào đúng để giết các tiến trình con trong perl trước khi thoát?
my $parent=$$;
my $proc_table=Proc::ProcessTable->new();
for my $proc (@{$proc_table->table()}) {
kill(15, $proc->pid) if ($proc->ppid == $parent);
}
Nó hoạt động nhưng tôi nhận được cảnh báo này:
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.
tôi có thể làm gì khác để giết tiến trình con? Quá trình chia đôi được tạo bằng phương thức forkit trong Bot::BasicBot.
Mẫu kịch bản:
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"; }
}
Xin chào, không có vấn đề gì với cách bạn đang giết các tiến trình con. Cảnh báo chỉ nói rằng bạn chưa đăng ký một cuộc gọi lại POE khi các quá trình này chết - bạn cần phải đăng ký chúng với POE-> kernel-> sig_child(). Xem: http://kobesearch.cpan.org/htdocs/POE/POE/Kernel.html#sig_child_PROCESS_ID_EVENT_NAME – Martin