2010-03-11 8 views
15

Io uso spesso il seguente schema per impostare un limite superiore per il tempo di esecuzione di un particolare frammento di codice in Perl:Modi per fare scadenze in Perl?

my $TIMEOUT_IN_SECONDS = 5; 
eval { 
    local $SIG{ALRM} = sub { die "alarm\n" }; 
    alarm($TIMEOUT_IN_SECONDS); 
    # do stuff that might timeout. 
    alarm(0); 
}; 
if ([email protected]) { 
    # handle timeout condition. 
} 

Le mie domande:

  • È questo il modo giusto per farlo?
  • Ci sono circostanze in cui il tempo di esecuzione può superare $ TIMEOUT_IN_SECONDS, o il metodo di cui sopra è a prova di proiettile?
+1

La tua valutazione è vulnerabile a un bug sgradevole. Leggi i documenti Try :: Tiny per una spiegazione dettagliata: http://search.cpan.org/perldoc?Try::Tiny – daotoad

risposta

9

probabilmente avrete bisogno di guardare Sys::SigAction. Non l'ho usato da solo, ma ha some glowing reviews.

Una cosa a cui fare attenzione è che se "roba che potrebbe timeout" utilizza sleep o alarm stesso. Inoltre, nel codice di gestione degli errori, presumo che tu sia preparato per errori diversi da un timeout.

+0

potresti spiegare il caso quando l'applicazione sta utilizzando sleep stesso? E come risolverlo? –

2

Fare attenzione alla gestione del segnale. Perl riceve segnali in modo asincrono e possono essere persi o interferire l'uno con l'altro se viene ricevuto un segnale mentre un altro segnale viene gestito dalla richiamata. Supporto Win32

librerie di gestione degli eventi è abbastanza così così in Perl (devo sostenere non Cygwin Win32), così ho generalmente utilizzare un ciclo di polling semplice per i timeout:

use Time::HiRes qw(sleep); 

sub timeout { 
    my $timeout = shift; 
    my $poll_interval = shift; 
    my $test_condition = shift; 
    until ($test_condition->() || $timeout <= 0) { 
    $timeout -= $poll_interval; 
    sleep $poll_interval; 
    } 
    return $timeout > 0; # condition was met before timeout 
} 

my $success = timeout(30, 0.1, \&some_condition_is_met); 

Il timer di spegnimento può essere facilmente reso configurabile dall'utente o del chiamante e, a meno che non si stia facendo un ciclo estremamente stretto o si abbiano più chiamanti in attesa sul loop (dove si può finire con una gara o blocco morto), è un semplice, affidabile e incrociato -modo semplice per implementare un timeout.

Si noti inoltre che l'overhead del loop significa che non è possibile garantire che il timeout sia osservato in modo assoluto. $ test_condition, il decremento, la garbage collection, ecc. possono interferire.

+1

Questo non risponde alla domanda. Questo codice non raggiungerà lo stesso obiettivo del codice dell'OP. Se some_condition_is_met() non ritorna mai, il programma si bloccherà. –

4

Si potrebbe anche provare Time::Out. Mi piace la sintassi e i timeout nidificati sono supportati ..

+1

+1 Questo modulo gestisce tutte le preoccupazioni relative ai timeout nidificati, ecc., In modo da non doversi preoccupare di tutti i casi limite. È allarmare ciò che prova :: tiny è quello di valutare. – mikew

+0

Il modulo Time :: Out è thread-safe? Nel mio caso ho bisogno di un timeout in esecuzione per thread nella mia applicazione. – reedog117

+0

@ reedog117: non ne ho idea ... –

Problemi correlati