Способы сделать тайм-ауты в Perl? - PullRequest
18 голосов
/ 11 марта 2010

Я часто использую следующий шаблон для установки верхней границы времени выполнения определенного фрагмента кода в 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, или вышеуказанный метод является пуленепробиваемым?

Ответы [ 3 ]

10 голосов
/ 11 марта 2010

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

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

4 голосов
/ 25 февраля 2013

Вы также можете попробовать Time :: Out . Мне нравится синтаксис и вложенные таймауты поддерживаются ..

2 голосов
/ 11 марта 2010

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

Поддержка Win32 в библиотеках обработки событий довольно проста в Perl (я должен поддерживать не-cygwin 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, декремент, сборка мусора и т. д. могут мешать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...