Я использую MCE, чтобы что-то делать, и он работает хорошо. Мне нужно посмотреть, как произойдет событие, а затем развить процесс MCE для обработки этого события. Это работает хорошо, но я столкнулся с проблемой, когда ошибка в дочернем процессе убивает родительский процесс, когда я думаю, что на него должен влиять только процесс MCE для детей. Вот короткая программа, демонстрирующая это поведение.Состояние демонаризованного процесса MCE влияет на родительский процесс
#!/usr/bin/perl
use strict;
use warnings;
use MCE::Loop;
use MCE::Signal '-setpgrp';
use POSIX "setsid";
$SIG{CHLD} = 'IGNORE';
my $mce_maxWorkers = 2;
my $mce_chunkSize = 1;
my @pids;
my $i = 0;
my $name = shift;
while ($i < 2) {
my $pid = fork();
if (!defined $pid) {
print "Can't fork: $!\n";
}
elsif ($pid == 0) {
#setpgrp(0,0);
(setsid() != -1) || die "Can't start a new session: $!";
MCE::Loop::init {
max_workers => $mce_maxWorkers,
chunk_size => $mce_chunkSize,
on_post_exit => sub {
my ($mce, $e) = @_;
print "$e->{wid}: $e->{pid}: status $e->{status}: $e->{msg}\n";
}
};
my $tail = 'tail -q -f '.$name;
open my $tail_fh, "-|", $tail or die "Can't open tail\n";
mce_loop_f {
my ($mce, $chunk_ref, $chunk_id) = @_;
my $line = ${$chunk_ref}[0];
chomp($line);
print $line."\n";
} $tail_fh;
close $tail_fh;
MCE->shutdown;
exit;
}
else {
print $pid."\n";
$i++;
push(@pids,$pid);
}
}
foreach my $p (@pids) {
waitpid $p, 0;
}
При запуске этой программы вилы двух детей обрабатывает этот хвост файл и прочитать его содержимое с петлей MCE, который имеет два рабочих процессов. Это приводит к 7 процессам, 1 родительскому, 2 менеджерам MCE и 4 работникам MCE (и 2 хвостовым процессам).
С помощью setid процессы диспетчера MCE должны быть отделены от родительского процесса. Все, что заставляет этих детей умирать, не должно влиять на родительский процесс правильно?
Речь идет о ps -efj | Grep монитор
user1 29001 978 29001 978 0 11:41 pts/2 00:00:00 /usr/bin/perl ./monitor1_test.pl tmp/monitor1/test1.log
user1 29002 29001 29002 29002 0 11:41 ? 00:00:00 /usr/bin/perl ./monitor1_test.pl tmp/monitor1/test1.log
user1 29003 29001 29003 29003 0 11:41 ? 00:00:00 /usr/bin/perl ./monitor1_test.pl tmp/monitor1/test1.log
user1 29004 29002 29002 29002 0 11:41 ? 00:00:00 tail -q -f tmp/monitor1/test1.log
user1 29005 29003 29003 29003 0 11:41 ? 00:00:00 tail -q -f tmp/monitor1/test1.log
user1 29006 29002 29002 29002 0 11:41 ? 00:00:00 /usr/bin/perl ./monitor1_test.pl tmp/monitor1/test1.log
user1 29007 29002 29002 29002 0 11:41 ? 00:00:00 /usr/bin/perl ./monitor1_test.pl tmp/monitor1/test1.log
user1 29008 29003 29003 29003 0 11:41 ? 00:00:00 /usr/bin/perl ./monitor1_test.pl tmp/monitor1/test1.log
user1 29009 29003 29003 29003 0 11:41 ? 00:00:00 /usr/bin/perl ./monitor1_test.pl tmp/monitor1/test1.log
Если бы я отправить SIGTERM в 29002 выше, я бы ожидать, что процесс, чтобы умереть вместе с 29004, 29006 и 29007. Я бы также ожидать, процесс 29001 и 29003 оставаться неизменным.
Однако я вижу, что 29001 умирает вместе с 29002, а 29003 остается. На терминале наблюдается следующая ошибка.
shell $ ./monitor1_test.pl tmp/monitor1/test1.log
29002
29003
test1234
test1234
## monitor1_test.pl: caught signal (INT), exiting
Killed
shell $ MCE::shutdown: method cannot be called while running at /usr/share/perl5/site_perl/MCE/Signal.pm line 371.
END failed--call queue aborted at ./monitor1_test.pl line 371, <$tail_fh> line 1.
Почему прекращение одного из дочерних процессов влияет на родителя таким образом? Я что-то делаю неправильно или делаю неверное предположение, что родитель должен это переживать? В настоящий момент я немного досаду, поэтому любой совет будет очень оценен.
Платформа: Linux 4.0.6 x86_64
Perl: 5,22
Вы отправляете SIGTERM, но родитель получил SIGINT? – ikegami
'kill ('INT', $ _is_MSWin32? - $$: -getpgrp);' в MCE :: Сигнал, вероятно, отвечает. – ikegami
@ikegami Спасибо, что ты прав. Я взломал Signal.pm, и есть несколько случаев, когда группа процессов убита, и есть ссылки на $ main_proc_id (родительский pid) в этих убийствах. Я уверен, что вокруг этого есть правильный путь, но это выглядит как первопричина. Благодаря! –