Si dimostrano gli arresti dei fork dei sottoprocessi nelle prove unitarie Perl; Test :: Imbracatura in uscita
-
06-07-2019 - |
Domanda
Ho cercato di utilizzare l'utilità / modulo Perl "dimostrare" come cablaggio di prova per alcuni test unitari. I test unitari sono un po 'più di "sistema" di "unità" come ho bisogno di interrompere alcuni processi in background come parte del test, utilizzando il seguente ...
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);
}
Tuttavia, per qualche motivo, quando ho il mio file .t che gira su alcuni processi extra, il cablaggio del test si blocca alla fine del primo file .t dopo che tutti i test sono terminati, piuttosto che passare al file successivo o uscire se ce n'è solo uno.
All'inizio mi chiedevo se potesse essere perché stavo uccidendo i miei sottoprocessi e li lasciavo defunti. Quindi ho aggiunto ..
$SIG{CHLD} = \&REAPER;
sub REAPER {
my $pid = wait;
$SIG{CHLD} = \&REAPER;
}
Al codice. Ma questo non aiuta. In effetti ad un esame chiuso risulta che il mio file di test perl è uscito e ora è un processo defunto ed è lo script wrapper di prova che non ha raccolto suo figlio. In effetti quando ho aggiunto una chiamata die () alla fine del mio script di test ho ricevuto ...
# Looks like your test died just after 7.
Quindi la mia sceneggiatura è uscita, ma per qualche ragione l'imbracatura non si sta dipanando.
Ho confermato che sono sicuramente i miei sottoprocessi a sconvolgerlo come quando li ho disabilitati mentre i test fallivano l'imbracatura è uscita correttamente.
C'è qualcosa che sto facendo di sbagliato nel modo in cui sto avviando i miei processi che potrebbe sconvolgere il cablaggio in qualche modo?
Grazie
Peter
Soluzione
Suppongo che tutti i tuoi figli siano usciti prima di lasciare il test? Perché altrimenti, potrebbe essere aggrappato a STDERR, il che potrebbe confondere la prova. Se potresti chiudere STDERR, o almeno reindirizzare a una pipe nel tuo processo genitore, questo potrebbe essere un problema che stai riscontrando.
Oltre a ciò, vorrei anche sottolineare che non è necessario sfuggire alle barre, e se non si utilizzano i metacaratteri della shell (gli spazi non sono metacaratteri perl - pensate " *? {} ()
"), dovresti essere esplicito e creare un elenco:
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";
Altri suggerimenti
Notare che non si verifica se fork ()
non è riuscito. Devi assicurarti che $ pid
sia definito prima di assumere che "falso" significa "bambino".
Poiché il tuo $ cmd
contiene metacaratteri (spazi) della shell, Perl sta effettivamente usando una shell quando chiami exec ()
. Mentre il monitor è in esecuzione, c'è (1) Perl, (2) un figlio sh -c
e (3) un nipote Perl che esegue monitor_real.pl
. Ciò che significa in particolare è quando chiami KillMonitor
, stai solo uccidendo la shell (perché è il PID che hai) e non il monitor.
Potresti anche essere interessato a Come faccio a fork un processo daemon? dalle FAQ Perl.