Как сделать так, чтобы приложение CGI :: Fast основывалось на уничтожении -HUP? - PullRequest
2 голосов
/ 19 марта 2009

У меня есть приложение, которое работает с использованием Perl's CGI :: Fast .

В основном основной цикл кода:

while (my $cgi = CGI::Fast->new() ) {
  do_whatever( $cgi );
}

Теперь я хотел добавить возможность убить его, но не прерывая обработанный в данный момент запрос. Для этого я добавил обработку в SIGHUP. Более или менее по линии:

my $sighupped = 0;
$SIG{ 'HUP' } = sub { $sighupped = 1; };
while (my $cgi = CGI::Fast->new() ) {
  do_whatever( $cgi );
  exit if $sighupped;
}

Что действительно хорошо работает, когда речь идет о "не мешающем процессе, пока он обрабатывает запрос пользователя". Но если процесс ожидает новый запрос, выход на основе sighup не будет выполнен, пока он, наконец, не получит некоторый запрос и не обработает его.

Есть ли какое-то решение для этого? Что я хотел бы добиться, чтобы скрипт немедленно завершил работу, если HUP (или другой сигнал, который можно изменить) достигает его во время ожидания запроса.

Ответы [ 2 ]

1 голос
/ 20 марта 2009

Вы можете использовать блочную версию функции eval и функции alarm, чтобы добавить время ожидания к Fast::CGI. В приведенном ниже коде я установил пятисекундный тайм-аут. Если время ожидания истекло, он вернется к началу цикла, который проверит, установлено ли значение $continue на ноль. Если этого не произошло, мы запускаем новый объект CGI::Fast. Это означает, что пройдет максимум пять секунд после того, как вы отправите HUP до того, как код начнет останавливаться, если он ожидал новый объект CGI::Fast (время ожидания не влияет на оставшуюся часть цикла).

my $continue = 1;
$SIG{HUP} = sub { $continue = 0 };
while ($continue) {
    my $cgi;
    eval {
        local $SIG{ALRM} = sub { die "timeout\n" };
        alarm 5; #set an alarm for five seconds
        $cgi = CGI::Fast->new;
        alarm 0; #turn alarm off
    };
    if ($@) {
        next if $@ eq "timeout\n"; #we will see the HUP signal's change now
        #died for a reason other than a timeout, so raise the error
        die $@;
    }
    last unless defined $cgi; #CGI::Fast has asked us to exit
    do_stuff($cgi);
}

#clean up
1 голос
/ 19 марта 2009

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

Если вы находитесь вне fast-cgi во время цикла или внутри fast-cgi, и, следовательно, не цикл события завершается (в основном по умолчанию). Если вы находитесь внутри логики Eventloop, дождитесь окончания и завершения логики.

Прошу прощения за отсутствие редактора на данный момент.

$inlogic=0;
$hupreq=0;
SIG{SIGHUP}={ exit unless($inlogic); $hupreq=1;}

while()
{
   $inlogic=1;
   function();
   $inlogic=0;
   exit if($hupreq);
}
...