Что правильный путь состоит в том, чтобы уничтожить дочерние процессы в жемчуге перед выходом?

Я выполняю 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"; }
}

5
задан rarbox 21 March 2010 в 17:38
поделиться

2 ответа

Я бы озаботился тем, почему дочерние процессы не завершаются должным образом. При "нормальных" обстоятельствах родитель не должен ничего делать (возможно, вызывать waitpid, если вам важны результаты, или останавливать обработку, пока они не закончатся).

Это еще не совсем ответ - вероятно, вам придется вставить часть кода в дочерние программы. Но небольшой совет -- начните с простых программ, которые вызывают fork вручную, а не полагайтесь на модуль CPAN, который сделает это за вас. Важно понять, как система обрабатывает несколько процессов. Затем, когда вы это поймете, вы сможете использовать какой-нибудь фреймворк для обработки множества процессов за вас.

Вам, вероятно, также следует прочитать perldoc perlfork, если вы не сделали этого недавно, и опробовать некоторые примеры.

0
ответ дан 15 December 2019 в 06:22
поделиться

Я не знаком ни с одним из упомянутых вами модулей, но когда я в прошлом писал forking Perl-программы, обычно было достаточно поместить эту строку в главный родительский процесс:

$SIG{CHLD} = sub { wait };

Таким образом, когда дочерний процесс завершается и родительский процесс получает сигнал SIGCHLD, он автоматически перезапускает дочерний с помощью wait.

1
ответ дан 15 December 2019 в 06:22
поделиться
Другие вопросы по тегам:

Похожие вопросы: