Estoy ejecutando un Bot de IRC (Bot::BasicBot) que tiene dos procesos secundarios que ejecutan File::Tail pero al salir, no terminan. Así que los estoy usando killling Proc::ProcessTable como esto antes de salir:¿Cuál es la forma correcta de matar procesos secundarios en perl antes de salir?
my $parent=$$;
my $proc_table=Proc::ProcessTable->new();
for my $proc (@{$proc_table->table()}) {
kill(15, $proc->pid) if ($proc->ppid == $parent);
}
Funciona pero me da esta advertencia:
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.
¿Qué más puedo hacer para matar procesos hijos? El proceso bifurcado se crea utilizando el método forkit en Bot::BasicBot.
Script de ejemplo:
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"; }
}
Hola, no hay ningún problema con la forma en que estás matando los procesos hijos. La advertencia solo indica que no ha registrado una devolución de llamada de POE para cuando estos procesos fallezcan; debe registrarlos con POE-> kernel-> sig_child(). Ver: http://kobesearch.cpan.org/htdocs/POE/KEEP/Kernel.html#sig_child_PROCESS_ID_EVENT_NAME – Martin