views:

577

answers:

2

Hi,

I have been trying to use the Perl utility/module "prove" as a test harness for some unit tests. The unit tests are a little more "system" than "unit" as I need to fork off some background processes as part of the test, Using the following...

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);
}

However for some reason when I have my .t file spin up some extra processes it causes the test harness to hang at the end of the first .t file after all the tests have finished, rather than going on to the next file, or exiting if there is only one.

At first I wondered if it might be because I was killing of my sub-processes and leaving them defunct. So I added..

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

To the code. But that doesn't help. In fact on closed examination it turns out that my perl test file has exited and is now a defunct process and it is the prove wrapper script that has not reaped its child. In fact when I added a die() call at the end of my test script I got...

# Looks like your test died just after 7.

So my script exited but for some reason the harness isn't unraveling.

I did confirm that it is definitely my sub-processes that are upsetting it as when I disabled them while the tests failed the harness exited properly.

Is there anything I am doing wrong with the way I am starting up my processes that might upset the harness in some way?

Thanks

Peter

+10  A: 
Kyle
+4  A: 

I'm assuming that all your kids have exited before you leave your test? Because otherwise, it may be hanging on to STDERR, which may confuse prove. If you could close STDERR, or at least redirect to a pipe in your parent process, that may be one issue you're having.

Besides that, I'd also point out that you don't need to escape forward slashes, and if you're not using shell metacharacters (spaces are not metacharacters to perl - think "*?{}()"), you should be explicit and create a list:

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";
Tanktalus
Thanks Tanktalus it turns out all I needed was to close STDERR as well as STDOUT. :-)
Vagnerr