1

I'm specificaly using AnyEvent::Inotify::Simple (using EV as backend) to monitor file events. So I have a handler callback that in a particular case, I need to "pause" before continuing. sleep obviously halts everything (so other events don't get handled until after sleep is done), so I tried using alarm however if the same scenario occurs that sets the alarm again, the original alarm (and therefore its $SIG{ALRM} sub) is ignored and only the "new" one is run.

#sleep-based approach (definitely a no-go)
sub handler {
    my ( $self, $event, $file ) = @_;
    #do some stuff
    ...
    if( $some_condition_exists ) {
        sleep(3);
        #now that we've waited, if some change occurred then do stuff
        if ( $new_change_occurred ) {
            #do some new stuff
        }
    }
    return;
}

#alarm -based approach (still a no-go when callback is called again while original alarm is still counting down)
sub handler {
    my ( $self, $event, $file ) = @_;
    #do some stuff
    ...
    if( $some_condition_exists ) {
        $SIG{ALRM} = sub {
             #now that we've waited, if some change occurred then do stuff
             if ( $new_change_occurred ) {
                 #do some new stuff
             }
        }
        alarm(3);
    }
    return;
}

Any advice would be appreciated? All I need is a way to make the callback pause while continuing to handle new inotify events asynchronously.

FunkyShu
  • 138
  • 5
  • 1
    Use `$cv->recv` to sleep, and do `$cv->send` when a change occurs. – ikegami Jan 15 '15 at 18:30
  • 1
    You use use `AE::timer(3, $cv);` to provide a timeout. – ikegami Jan 15 '15 at 18:59
  • AnyEvent->timer() was probably the correct approach and I had already tried it but never got it to work from within the AnyEvent::Inotify::Simple event_receiver callback. I'm not sure if it somehow conflicted with running EV loop (tied to inotify) or just the wrong usage. At any rate, my solution, was using POE::Session delay_add. It seems a bit crazy to introduce another event framewok(especially one so bulky) to the same app but it did work. I considered using POEx::Inotify instead of AnyEvent::Inotify::Simple but it wouldn've meant a significant rewrite of my app. Thanks for the help! – FunkyShu Feb 19 '15 at 17:28
  • If you're in `recv`, the event queue will be checked for the timer event, so it can be used to make a timeout. – ikegami Feb 19 '15 at 18:10

1 Answers1

1

When using an AnyEvent::timer, make sure you keep track of the guard object it returns. I typically store them in a global.

If you assign it to a variable that goes out of scope, the timer will be canceled.

my $guards;

sub handler {
    my ( $self, $event, $file ) = @_;
    #do some stuff
    ...
    if( $some_condition_exists ) {
        $guards->{$file} = AE::timer 3,0,sub {
             #now that we've waited, if some change occurred then do stuff
             if ( $new_change_occurred ) {
                 #do some new stuff
             }
        };
    }
    return;
}
TheAmigo
  • 1,032
  • 1
  • 10
  • 29
  • Yep, that's exactly what was happening. The timer fell out of scope when the handler callback returned and died a quiet death. A "duh" moment but thanks for pointing it out! – FunkyShu Jun 18 '15 at 17:09