2015-09-20 2 views
0

Итак, я занимаюсь поиском здесь, а также на perl.org и perlmaven.com, но я смущен тем, что происходит с кодом, который я пытаюсь бежать. Я гугле, что $ SIG это и нашел что-то на here, что дает мне немного идея о том, что местный $ SIG это, но я до сих пор смущает то, что он имел в виду под этим:Perl: Позвоните подпрограмму Каждые 15 секунд

Perl имеет встроенный хэш с именем% SIG, в котором ключи являются именами сигналов, доступных в вашей операционной системе. Значения - это подпрограммы (более конкретно ссылки на подпрограммы), которые будут вызываться, когда поступает конкретный сигнал.

В дополнение к стандартным сигналам вашей операционной системы Perl добавил два внутренних «сигнала». Один из них называется WARN и запускается каждый раз, когда какой-то код вызывает функцию warn(). Другой называется DIE, и он запускается при вызове функции die().

Он также говорит о here, что я не должен смешивать вызовы сна в течение вызова тревоги, но то, что объяснить, похоже, как и другой язык для меня. Я в замешательстве. У меня возникли проблемы с выходом из подпрограммы без того, чтобы она не умирала от меня. код, который я бегу это (я получил его от другого поста здесь, но я не хочу, чтобы оживить этот пост, как это с 2011 года):

sub checkfind { 
didfindchange; 
    while ($call_counter <= 20) { 
     my $previous_call_finished = 0; 
     eval { 
      local $SIG{ALRM} = sub { die "Alarm.\n" }; 
      alarm 15; 
      if ($did_find_change eq "false") { 
       didfindchange; 
       print("Original FIND value: $original_find_value\n"); 
       print("FIND value: $ems_find_value\n"); 
      } 
      elsif ($did_find_change eq "true") { 
       print("FIND changed.\n"); 
       print("Original FIND value: $original_find_value\n"); 
       print("FIND value: $ems_find_value\n"); 
       $previous_call_finished = 1; 
      } 
      sleep; 
     }; 
     #Propagate unexpected errors. 
     die unless [email protected] eq "Alarm.\n"; 
     warn "Timed out!\n" unless $previous_call_finished 
    } 
    return; 
} 

Моя программа просто продолжает умирать, и я «Не знаю, почему. Любая помощь будет оценена по достоинству. Спасибо!

+0

почему вы спать? если на то пошло, опишите на английском то, что вы пытаетесь сделать – ysth

+0

Я хочу называть didfindchange() каждые 15 секунд. Если значение FIND изменится, выйдите из подпрограммы. Если значение FIND не изменяется, завершение работы по истечении пяти минут истекает. Я вызываю sleep(), потому что по какой-то причине подпрограмма просто умирает, если я этого не делаю. @ysth –

ответ

2

Как правило, можно использовать аварийный сигнал для подпрограмм/внешних процессов, которые могут занять много времени (ожидание соединения db, сетевой ресурс, действительно дорогостоящий расчет и т. Д.). Вы должны каждый раз перезапускать тревогу после завершения задачи. alarm(0); Для того, что я понимаю, что вы пытаетесь сделать, для вас должен работать простой цикл сна/таймаута, такой как следующий. Для чего-то более сложного (ожидание файлов событий, сетевых событий), вы можете рассмотреть вопрос о программировании с событием EV петли perldoc EV или библиотеку AnyEvent perldoc AnyEvent

#!/usr/bin/env perl 

use warnings; 
use strict; 

use constant TIMEOUT => 10; 
use constant SLEEP => 2; 

check_for_something(); 
exit 0; # Success 

sub check_for_something { 
    my $start_time = time(); 
    my $elapsed = 0; 
    while ($elapsed < TIMEOUT) { 
     print "$elapsed seconds have elapsed..."; 
     my $value = look_for_something(); 
     print "Value is " . ($value ? 'true' : 'false') . "\n"; 
     if ($value) { 
      print "Value is true...returning\n"; 
      return "value has changed..."; 
     } 

     sleep SLEEP; 
     $elapsed = time() - $start_time; 
    } 
    die "Timed out after " . TIMEOUT . " seconds!\n"; 
} 

sub look_for_something { 
    # !! changes the number into either '1' or 'undef' 
    # ! !! inverts the sense 
    return ! !! int rand (2 * TIMEOUT/SLEEP); # False most of the time, occasionaly true  
} 

Выход

perl test_find.pl 
0 seconds have elapsed...Value is false 
2 seconds have elapsed...Value is false 
4 seconds have elapsed...Value is false 
6 seconds have elapsed...Value is false 
8 seconds have elapsed...Value is false 
Timed out after 10 seconds! 

perl test_find.pl 
0 seconds have elapsed...Value is false 
2 seconds have elapsed...Value is false 
4 seconds have elapsed...Value is true 
Value is true...returning 
+0

Спасибо за ответ, кажется, что вы правы и мне не нужно использовать аварийные сигналы. Однако в вашем ответе было несколько вещей, которые меня заинтриговали. Почему вы используете ($ start_time) вместо $ star_time (без круглых скобок)? Когда вы печатаете то, что имеет значение $ ($ value? 'True': 'false'), ограничивайте, какое значение $ может быть только true или false? Почему у вас есть две функции check_for_something() и выход 0; прямо под одним? И можете ли вы объяснить оператор return_for_something()? Я озадачен восклицательными знаками. В любом случае, спасибо за ваш ответ. @xxfelixxx –

+0

Круглые скобки вокруг '($ start_time)' не нужны, поэтому я их удалил. Они исходили из привычки стараться избегать ошибок контекста списка-vs-scalar. '$ value' устанавливается как' 1', так и 'undef', поэтому я преобразую его в строку 'true' или 'false' через тернарный оператор.Первый 'check_for_something()' вызывает подпрограмму, которая определена позже. «Выход 0» - это то, что вы можете рассуждать о потоке кода (просто потому, что вы «можете» интерполировать код и подпрограммы, не означает, что это хорошо для следующего программиста ... – xxfelixxx

+0

Что касается '!!' и '!!!', хотя я бы обескураживал такие конструкции в любом реальном (производственном) коде, они являются частью perl-овских «секретных» операторов: http://search.cpan.org/~book/perlsecret-1.013/ Библиотека/perlsecret.pod – xxfelixxx

Смежные вопросы