代码之家  ›  专栏  ›  技术社区  ›  Vagnerr

在Perl单元测试中分叉子进程;测试::线束正在退出

  •  13
  • Vagnerr  · 技术社区  · 16 年前

    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.
    

    我确实确认了,确实是我的子进程在扰乱它,就像我在测试失败时禁用它们,线束正确退出一样。

    我启动流程的方式是否有任何错误,可能会以某种方式打乱安全带?

    2 回复  |  直到 3 年前
        1
  •  12
  •   Kyle    16 年前

    fork() 失败。你需要确认一下 $pid defined 在假设“false”的意思是“child”之前

    $cmd 包含shell元字符(空格),当您调用 exec() . 当您的监视器运行时,有(1)个Perl,(2)个孩子 sh -c ,以及(3)运行Perl的孙子 monitor_real.pl . 特别是当你打电话的时候 KillMonitor

    您可能也对以下内容感兴趣: How do I fork a daemon process? 来自Perl常见问题解答。

        2
  •  8
  •   Tanktalus    16 年前

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

    除此之外,我还想指出,您不需要逃避正斜杠,如果您没有使用shell元字符(空格对于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";