我一直在尝试使用Perl实用程序/模块“证明”作为一些单元测试的测试工具。单元测试是更多的“系统”测试。而不是“单位”因为我需要将一些后台进程分解为测试的一部分,使用以下...

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测试文件已经退出并且现在已经不存在了,并且它是证明包装器脚本没有收到它的孩子。事实上,当我在测试脚本的末尾添加了一个die()调用时,我得到了......

# Looks like your test died just after 7.

所以我的脚本退出了,但由于某种原因,线束没有解开。

我确实确认我的子流程肯定会让我感到不安,因为当我在测试失败时正确地退出线圈时我会禁用它们。

我启动流程的方式是否有什么问题,可能会以某种方式扰乱线束?

由于

彼得

有帮助吗?

解决方案

我假设你的孩子在离开考试前已经退出了吗?因为否则,它可能会挂在STDERR上,这可能会混淆证明。如果您可以关闭STDERR,或者至少重定向到父进程中的管道,那么这可能是您遇到的一个问题。

除此之外,我还要指出你不需要转义正斜杠,如果你没有使用shell元字符(空格不是perl字符到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 包含shell元字符(空格),所以当你调用 exec()时,Perl实际上正在使用shell。在您的监视器运行时,有(1)Perl,(2)子 sh -c ,以及(3)运行 monitor_real.pl 的孙子Perl。特别是当你调用 KillMonitor 时,你只是杀死了shell(因为那是你拥有的PID),而不是监视器。

你可能也对如何从Perl FAQ中分叉守护进程?

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top