Разветвление подпроцессов в модульных тестах Perl прекращает доказывать;Тест:: Выход жгута проводов

StackOverflow https://stackoverflow.com/questions/183560

Вопрос

Я пытался использовать утилиту Perl / модуль "prove" в качестве тестового набора для некоторых модульных тестов.Модульные тесты немного более "системные", чем "модульные", поскольку мне нужно отключить некоторые фоновые процессы как часть теста, используя следующее...

sub SpinupMonitor{
   my $base_dir = shift;
   my $config = shift;

   my $pid = fork();
   if($pid){
      return $pid;
   }else{
      my $cmd = "$base_dir\/..\/bin\/monitor_real.pl -config $config -test";
      close STDOUT;

      exec ($cmd) or die "cannot exec test code [$cmd]\n";
   }
}

sub KillMonitor{

   my $pid = shift;

   print "Killing monitor [$pid]\n";
   kill(1,$pid);
}

Однако по какой-то причине, когда мой файл .t запускает некоторые дополнительные процессы, это приводит к зависанию тестового жгута в конце первого файла .t после завершения всех тестов, вместо перехода к следующему файлу или выхода, если есть только один.

Сначала я подумал, может быть, это из-за того, что я убивал свои подпроцессы и оставлял их неработоспособными.Поэтому я добавил..

$SIG{CHLD} = \&REAPER;
sub REAPER {
   my $pid = wait;
   $SIG{CHLD} = \&REAPER;
}

К коду.Но это не помогает.Фактически, при закрытой проверке выясняется, что мой тестовый файл perl завершился и теперь является несуществующим процессом, и это скрипт-оболочка prove, который не извлек своего дочернего элемента.На самом деле, когда я добавил вызов die() в конце моего тестового скрипта, я получил...

# Looks like your test died just after 7.

Итак, мой сценарий завершен, но по какой-то причине жгут не распутывается.

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

Есть ли что-то, что я делаю неправильно в том, как я запускаю свои процессы, что может каким-то образом нарушить работу ремня безопасности?

Спасибо

Питер

Это было полезно?

Решение

Я предполагаю, что все ваши дети закончили обучение до того, как вы закончили свой тест?Потому что в противном случае он может зависнуть на STDERR, что может сбить с толку prove.Если бы вы могли закрыть STDERR или, по крайней мере, перенаправить на канал в вашем родительском процессе, это могло бы быть одной из проблем, с которой вы столкнулись.

Кроме того, я бы также отметил, что вам не нужно избегать косых черт, и если вы не используете метасимволы оболочки (пробелы не являются метасимволами в perl - подумайте "*?{}()"), вы должны быть откровенны и создать список:

use File::Spec;
my @cmd = File::Spec->catfile($basedir,
                              File::Spec->updir(),
                              qw(bin monitor_real.pl)
                             ),
          -config => $config,
          -test   =>;

close STDOUT;
close STDERR;

exec (@cmd) or die "cannot exec test code [@cmd]\n";

Другие советы

Обратите внимание, что вы не проверяете, является ли fork() потерпел неудачу.Вам нужно убедиться $pid является определенный прежде чем предположить, что "ложный" означает "дочерний".

Потому что ваш $cmd содержит метасимволы оболочки (пробелы), Perl фактически использует оболочку при вызове exec().Пока ваш монитор работает, есть (1) Perl, (2) дочерний sh -c, и (3) дочерний Perl , работающий monitor_real.pl.В частности, это означает, что когда вы звоните KillMonitor, вы уничтожаете только оболочку (потому что это ваш PID), а не монитор.

Вас также могут заинтересовать Как мне разветвить демонический процесс? из часто задаваемых вопросов по Perl.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top