Способы сделать тайм-ауты в Perl?

Я часто использую следующий шаблон для установки верхней границы на время выполнения конкретного фрагмента кода в 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 ($@) {
    # handle timeout condition.
}

Мои вопросы:

  • Действительно ли это - правильный способ сделать это?
  • Есть ли какие-либо обстоятельства, при которых время выполнения может превысить $TIMEOUT_IN_SECONDS или является вышеупомянутым пуленепробиваемым методом?
20
задан knorv 11 March 2010 в 07:37
поделиться

2 ответа

Вы, вероятно, захотите посмотреть Sys :: SigAction . Я сам им не пользовался, но у него есть несколько восторженных отзывов .

Одна вещь, на которую следует обратить внимание, - это если "вещи, которые могут отключиться по таймауту", используют сами сна или будильник . Кроме того, в коде обработки ошибок я предполагаю, что вы готовы к ошибкам, отличным от тайм-аута.

10
ответ дан 30 November 2019 в 01:20
поделиться

Будьте осторожны с обработкой сигналов. Perl получает сигналы асинхронно, и они могут быть потеряны или мешать друг другу, если сигнал получен в то время, когда другой сигнал обрабатывается обратным вызовом.

Поддержка Win32 библиотеками обработки событий довольно слабая в Perl (мне приходится поддерживать не-цигвин Win32), поэтому я обычно использую простой цикл опроса для тайм-аутов:

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);

Таймер сна можно легко сделать настраиваемым пользователем или вызывающей стороной, и если вы не делаете очень узкий цикл или у вас есть несколько вызывающих сторон, ожидающих цикл (где вы можете получить гонку или мертвую блокировку), это простой, надежный и кросс-платформенный способ реализации тайм-аута.

Также обратите внимание, что накладные расходы цикла означают, что вы не можете гарантировать абсолютное соблюдение тайм-аута. $test_condition, декремент, сборка мусора и т.д. могут помешать.

2
ответ дан 30 November 2019 в 01:20
поделиться
Другие вопросы по тегам:

Похожие вопросы: