RandomAndy
RandomAndy

Reputation: 354

AnyEvent->timer not working with AnyEvent::Handle?

I'm trying to build a timeout scenario in my Catalyst, AnyEvent, Websocket app. For that I'm using

AnyEvent->timer

which should be called after let's say a few seconds of inactivity (no more WS frames coming in).

The problem is, that my timer is never executed:

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) {
        ...
    }

The timer callback is never executed. My guess would be, that the timer doesn't work inside another Event loop (AnyEvent::Handle)?

Upvotes: 4

Views: 620

Answers (1)

paulw1128
paulw1128

Reputation: 464

Are you actually getting into the event loop for the timer to be processed? Your code snippet does not indicate this.

Also, AnyEvent::Handle has inactivity timeouts built-in:

       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.

Upvotes: 3

Related Questions