Я выполняю 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.
Что еще я могу сделать для уничтожения дочерних процессов? Разветвленный процесс создается с помощью forkit метода в Bot:: BasicBot.
Демонстрационный сценарий:
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"; }
}
Я бы озаботился тем, почему дочерние процессы не завершаются должным образом. При "нормальных" обстоятельствах родитель не должен ничего делать (возможно, вызывать waitpid
, если вам важны результаты, или останавливать обработку, пока они не закончатся).
Это еще не совсем ответ - вероятно, вам придется вставить часть кода в дочерние программы. Но небольшой совет -- начните с простых программ, которые вызывают fork
вручную, а не полагайтесь на модуль CPAN, который сделает это за вас. Важно понять, как система обрабатывает несколько процессов. Затем, когда вы это поймете, вы сможете использовать какой-нибудь фреймворк для обработки множества процессов за вас.
Вам, вероятно, также следует прочитать perldoc perlfork, если вы не сделали этого недавно, и опробовать некоторые примеры.
Я не знаком ни с одним из упомянутых вами модулей, но когда я в прошлом писал forking Perl-программы, обычно было достаточно поместить эту строку в главный родительский процесс:
$SIG{CHLD} = sub { wait };
Таким образом, когда дочерний процесс завершается и родительский процесс получает сигнал SIGCHLD, он автоматически перезапускает дочерний с помощью wait
.