2014-12-28 19 views
8

Nello script seguente sto cercando di capire come funziona waitpid, ma non attende il processo ssh per uscire. done viene stampato subito dopo il processo ssh.Perché waitpid non attende l'uscita del processo?

Domanda

Come Faccio waitpid continuare solo quando il pid dò usciti?

#!/usr/bin/perl 
use strict; 
use warnings; 
use Parallel::ForkManager; 
use POSIX ":sys_wait_h"; 

my $pm = Parallel::ForkManager->new(5); 
my $pid = $pm->start; 
my $p = $pid; 
if (!$pid) { 
    system("ssh 10.10.47.47 sleep 10"); 
    $pm->finish; 
} 

$p = qx(/usr/bin/pgrep -P $p); 
print "ssh pid is $p\n"; 

my $kid; 
do { 
    $kid = waitpid($p, 0); 
} while $kid > 0; 

print "done\n"; 

Ho anche provato

while (1) { 
    $p = kill 0, $p; 
    print "x"; 
    sleep 1 if $p; 
    print "*"; 
    last unless $p; 
} 

ma non raggiunge neppure la prima print per qualche motivo e mai uscite.

risposta

8

La famiglia di funzioni wait funziona solo su processi figlio, anche waitpid. Il processo del sonno non è tuo figlio, è il figlio di tuo figlio. Questo perché system è essenzialmente fork + exec. Usando il sistema Parallel :: ForkManager + si sta biforcandosi, quindi si biforca di nuovo, quindi si esegue il sonno.

Poiché hai già biforcato, dovresti usare exec. Questo ha il vantaggio in più di non aver bisogno della chiamata a pgrep e il suo problema di temporizzazione (cioè è possibile che il genitore chiamerà pgrep prima che il bambino abbia eseguito il sistema).

my $pm = Parallel::ForkManager->new(5); 
my $pid = $pm->start; 
my $p = $pid; 
if (!$pid) { 
    no warnings; # no warnings "exec" is not working 
    exec("sleep 10"); 
    $pm->finish; 
} 

print "sleep pid is $p\n"; 
waitpid($p, 0); 

Per semplicità ora utilizza il sonno. Un avvertimento di Perl che "Dichiarazione improbabile da raggiungere" deve essere soppressa perché Perl non si rende conto che $pm->start ha biforcuto. Questo dovrebbe essere no warnings "exec" ma non funziona, quindi ho dovuto sopprimerli tutti.