2014-11-03 2 views
2

Я пытаюсь построить тайм-аут в своем приложении Catalyst, AnyEvent, Websocket. Для этого я используюAnyEvent-> таймер, не работающий с AnyEvent :: Handle?

AnyEvent->timer 

, который должен быть вызван после того, как, скажем, через несколько секунд бездействия (не более WS ФРЕЙМАМИ поступают).

Проблема заключается в том, что мой таймер никогда не выполняется:

my $w = AnyEvent->timer (after => 3, 
         cb => sub { 
    warn "TIMEOUT!"; 
}); 

$self->{server} = Protocol::WebSocket::Handshake::Server->new_from_psgi(
          $c->req->env) or die $c->log->fatal($!); 

$self->{handle} = AnyEvent::Handle->new(
    fh => $c->req->io_fh, 
    on_error => sub { 
     my ($hd, $fatal, $msg) = @_; 
     $clean_up->(); 
    } 
); 

die $c->log->fatal("WS Server error: '$_'") 
     if $self->{server}->error; 

$self->{server}->parse($self->{handle}->fh); 
$self->{handle}->push_write($self->{server}->to_string); 

$self->{handle}->on_read(sub { 
    (my $frame = $self->{server}->build_frame)->append($_[0]->rbuf); 

    while (my $frame_msg = $frame->next) { 
     ... 
    } 

обратного вызова таймера никогда не выполняется. Я предполагаю, что таймер не работает внутри другого цикла событий (AnyEvent :: Handle)?

+0

мог бы вы сделать работоспособную демонстрацию проблемы, которая не использует протокол :: WebSocket :: Рукопожатие :: Сервер? (например, он может читать из STDIN, который может быть передан из «perl -E» $ | = 1, например «abc»; sleep 4, say «def»; '). Ваша проблема бесполезна недоступна (если она не связана с протоколом :: WebSocket :: Handshake :: Server, и в этом случае его следует упомянуть). – ikegami

+0

Если весь код, отправленный в вопросе, находится в функции, то, как только эта функция выйдет, $ w выходит за рамки, что отменяет таймер. – TheAmigo

ответ

3

Вы действительно попадаете в цикл событий для обрабатываемого таймера? Этот фрагмент кода не указывает на это.

Кроме того, AnyEvent::Handle имеет таймаут встроенный:

 timeout => $fractional_seconds 
      If non-zero, then this enables an "inactivity" timeout: whenever 
      this many seconds pass without a successful read or write on the 
      underlying file handle, the "on_timeout" callback will be invoked 
      (and if that one is missing, a non-fatal "ETIMEDOUT" error will 
      be raised). 

      Note that timeout processing is also active when you currently do 
      not have any outstanding read or write requests: If you plan to 
      keep the connection idle then you should disable the timout 
      temporarily or ignore the timeout in the "on_timeout" callback, 
      in which case AnyEvent::Handle will simply restart the timeout. 

      Zero (the default) disables this timeout. 

     on_timeout => $cb->($handle) 
      Called whenever the inactivity timeout passes. If you return from 
      this callback, then the timeout will be reset as if some activity 
      had happened, so this condition is not fatal in any way.