Perl: вызов подпрограммы каждые 15 секунд

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

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

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

Здесь также говорится, что здесь, что мне не следует смешивать вызовы сна с вызовом будильника, но то, что там объясняется, мне кажется другим языком. Я запуталась. У меня проблемы с выходом из подпрограммы, чтобы она не умерла от меня. Я запускаю следующий код (я получил его из другого сообщения здесь, но я не хочу восстанавливать этот пост, поскольку он с 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 $@ eq "Alarm.\n";
        warn "Timed out!\n" unless $previous_call_finished
    }
    return;
}

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


person René Alejandro Santiago    schedule 20.09.2015    source источник
comment
почему ты спишь? если на то пошло, опишите на английском, что вы пытаетесь сделать   -  person ysth    schedule 21.09.2015
comment
Я хочу вызывать didfindchange () каждые 15 секунд. Если значение FIND изменилось, выйти из подпрограммы. Если значение FIND не меняется, выйдите из подпрограммы по истечении пяти минут. Я вызываю sleep (), потому что по какой-то причине подпрограмма просто умирает, если я этого не сделаю. @ysth   -  person René Alejandro Santiago    schedule 21.09.2015


Ответы (1)


Как правило, можно использовать аварийный сигнал для подпрограмм / внешних процессов, которые могут занять много времени (ожидание подключения к базе данных, сетевого ресурса, действительно дорогостоящих вычислений и т. Д.). Вы должны сбрасывать сигнал тревоги каждый раз после завершения задачи 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
person xxfelixxx    schedule 20.09.2015
comment
Спасибо за ответ, кажется, вы правы и мне не пришлось использовать будильники. Однако в вашем ответе было несколько вещей, которые меня заинтриговали. Почему вы используете ($ start_time) вместо $ star_time (без скобок)? Когда вы печатаете, что такое $ value ($ value? 'True': 'false') ограничивает, какое значение $ value может быть только истинным или ложным? Почему у вас есть две подпрограммы check_for_something () и выход 0; прямо под одним? А вы можете объяснить оператор return look_for_something ()? Меня озадачивают восклицательные знаки. В любом случае, спасибо за ваш ответ. @xxfelixxx - person René Alejandro Santiago; 21.09.2015
comment
Скобки вокруг ($start_time) не нужны, поэтому я их убрал. Они возникли из-за привычки избегать ошибок контекста «список-скаляр». $value имеет значение 1 или undef, поэтому я конвертирую его в строку «истина» или «ложь» с помощью тернарного оператора. Первый check_for_something() вызывает подпрограмму, которая определена позже. exit 0 предназначен для того, чтобы вы могли рассуждать о потоке кода (то, что вы can перемежаете код и подпрограммы, не означает, что это хорошо для следующего программиста ... - person xxfelixxx; 22.09.2015
comment
Что касается !! и !!!, хотя я бы не одобрял такие конструкции в любом реальном (производственном) коде, они являются частью perl lore secret операторов: search.cpan.org/~book/perlsecret-1.013/lib/perlsecret.pod - person xxfelixxx; 22.09.2015