Andre_br has asked for the wisdom of the Perl Monks concerning the following question:

Hello my esteemed monks,

I need to set a timeout for an operation I perform inside a while loop, but Iīm having trouble understanding the dinamic of the alarm() function. Can you guys help me out? Hereīs the (wrong!) code:

$SIG{ALRM} = sub { print "...timeout"; next READING; }; my $number = 1; READING: while ( $number < 10 ) { eval { alarm(3); print $number; if ( $number == 3 ) { sleep 4; } # This is to simulate the delay + the routines may generate... $number++; print "\n"; } } if ($@) { # this I copied from the Camel book, but not sure about what + it means and if it is really necessary in this case... (I donīt want + to 'die'; i just want to go to the 'next' iteration.) if ($@ =~ /timeout/) { # timed out; do what you will here } else { alarm(0); # clear the still-pending alarm die; # propagate unexpected exception } }
Thanks a lot fellows,

Andre_br

Replies are listed 'Best First'.
Re: How to timeout a while loop?
by suaveant (Parson) on Apr 25, 2005 at 20:13 UTC
    You want a die 'timeout'; in your $SIG{ALRM} that will break you out at the end of your eval (put a ; at the end of that eval) then put your code catch code... like so

    $SIG{ALRM} = sub {die 'timeout'}; while ( $number < 10 ) { eval { alarm(3); print $number; if ( $number == 3 ) { sleep 4; } # This is to simulate the delay + the routines may generate... $number++; print "\n"; }; alarm(0); if($@ eq 'timeout') { next; } else { die $@; } }
    Not tested, but should get you pointed in the right direction. Alarm 0 is important to unset the alarm.

                    - Ant
                    - Some of my best work - (1 2 3)

      Hey Suaveant,

      Great! Thanks a lot; in fact i needed to change some details for it to work, like putting the sub that listens the $@ outside the while, but now it is just perfect.

      Hereīs the final code, for the monk's record:

      my $number = 0; $SIG{ALRM} = sub {die 'timeout'}; while ( $number < 10 ) { eval { $number++; alarm(3); if ( $number == 3 ) { sleep 4; } # This is to simulate the delay + the routines may generate... print $number; print "\n"; }; alarm(0); } if($@ eq 'timeout') { next; } else { die $@; }
      Thanks a lot, my friend

      Andre_br

        Umm.. if you leave the if at the bottom outside the while the next is useless, and any $@ values will cause the loop to continue, including non-timeout values. You could possibly also miss valid die messages. To be really useful you should probably check the $@ at the end of the eval after the alarm(0);

                        - Ant
                        - Some of my best work - (1 2 3)