我一直在尝试使用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.所以我的脚本退出了,但是由于某些原因,这个线束并没有解开。
我确实确认了肯定是我的子进程使它不稳定,因为当我禁用它们时,测试失败了,线束正确退出。
我启动进程的方式有没有做错什么,可能会以某种方式扰乱安全带?
发布于 2008-10-08 21:07:24
我猜你所有的孩子在你离开考试前都已经离开了?因为否则,它可能会挂在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";发布于 2008-10-08 16:32:45
请注意,您不会测试fork()是否失败。在假设“defined”表示“defined”之前,您需要确保false为子级。
因为$cmd包含外壳元字符(空格),所以当您调用exec()时,实际上是在使用外壳。当您的监视器正在运行时,有(1) Perl、(2)子sh -c和(3)运行monitor_real.pl的孙子Perl。这特别意味着,当您调用KillMonitor时,您只杀死了外壳(因为这是您拥有的PID ),而不是监视器。
您可能还会对Perl FAQ中的How do I fork a daemon process?感兴趣。
https://stackoverflow.com/questions/183560
复制相似问题