2016-01-25 20 views
8

Ho bisogno di timeout su uno script che sta bloccando io.
Sorprendentemente si scopre exit si blocca se non v'è un tubo aperto a un sottoprocesso:Perl: la chiusura della sottoprocesso nel gestore di segnale si blocca?

#!/usr/bin/perl                        
(-f "foo") || die "file foo doesn't exist"; 
open(IN, "tail -f foo |"); 

$SIG{ALRM} = sub 
{ 
    print "trying to exit...\n"; 
    exit 0;  # Hangs with above open() call 
}; 
alarm 1; 

while (1) 
{ 
    sleep 5; # Do stuff ... 
} 

Senza open chiamata funziona, purtroppo la rimozione non è un'opzione in questo caso lo script ha bisogno.

Sembra exit sta cercando di chiudere il filehandle e questo è ciò che è appeso:

$SIG{ALRM} = sub 
{ 
    print "trying to close...\n"; 
    close(IN);   # Hangs ... 
    print "ok\n"; 
    exit 0; 
}; 

Credo che non sia troppo felice di cogliere il bambino da dentro un gestore di segnale ...

fa qualcuno conosce un buon modo per aggirare questo?

risposta

10

Il gestore del segnale è una falsa pista, close bloccherà a prescindere:

open my $foo, "tail -f foo |" or die "Can't open process: $!"; 

close $foo;  # <--- will block 

Un modo per risolvere questo problema è quello di catturare l'ID di processo sub via open e poi kill quel bambino:

my $subprocess = open my $foo, "tail -f foo |" or die "Can't open process: $!"; 

say "subprocess=$subprocess"; 

kill 'KILL', $subprocess; 

close $foo;  # <--- happy now 
+1

Certo che hai perfettamente ragione, stupido! La parte confusa era che una "uscita" iniziale funziona davvero, ma solo perché crea una condizione di competizione (il bambino non è ancora pronto). Grazie ! – lemonsqueeze

1

Utilizzare POSIX::_exit() direttamente come suggerisce la pagina man sembra aggirare questo particolare problema. Ma questo odora di un problema A-B. Sei sicuro che il tuo vero problema non si risolva meglio utilizzando un modo più sofisticato di gestire i sottoprocessi rispetto ai tubi semplici, come ad esempio IPC::Run?

+0

Anche questo funziona, ma il processo 'tail' viene lasciato in esecuzione e diventa orfano ... – lemonsqueeze