4

I have been searching on this but it is surprisingly hard to come by a straight answer to this (as php has a lot more info on this topic it seems).. I need to make my perl script die after a specified number of seconds because, as it is now, they are running too long and clogging up my system, how can I make it so the entire script just dies after a specified number of seconds?

I know about external solutions to kill the script but I would like to do it from within the perl script itself.

Thanks

Rick
  • 16,612
  • 34
  • 110
  • 163
  • Also see related question http://stackoverflow.com/questions/3238118/perl-alarm-working-intermittently – runrig Aug 06 '10 at 22:34

2 Answers2

12

perldoc -f alarm:

[sinan@kas ~]$ cat t.pl
#!/usr/bin/perl

use strict; use warnings;

use Try::Tiny;

try {
        local $SIG{ALRM} = sub { die "alarm\n" };
        alarm 5;
        main();
        alarm 0;
}
catch {
        die $_ unless $_ eq "alarm\n";
        print "timed out\n";
};

print "done\n";

sub main {
        sleep 20;
}

Output:

[sinan@kas ~]$ time perl t.pl
timed out
done

real    0m5.029s
user    0m0.027s
sys     0m0.000s
Sinan Ünür
  • 116,958
  • 15
  • 196
  • 339
  • thanks.. this helps me understand it better, I couldn't really wrap my head around the alarm function as the examples seem sparse in the documentation, I will try that – Rick Aug 06 '10 at 20:22
  • ONE question.. where would my actual script's code go? In the first "try" bracket? I think thats what has been confusing me on using alarm – Rick Aug 06 '10 at 20:23
  • @Rick: Put your code in the `main` function (or any other suitably named function). That way, you do not have too many levels of nesting. – Sinan Ünür Aug 06 '10 at 20:25
2

See alarm in perldoc:

eval {
    local $SIG{ALRM} = sub { die "alarm\n" }; # NB: \n required
    alarm $timeout;
    $nread = sysread SOCKET, $buffer, $size;
    alarm 0;
};
if ($@) {
    die unless $@ eq "alarm\n";   # propagate unexpected errors
    # timed out
}
else {
    # didn't
}
Pedro Silva
  • 4,672
  • 1
  • 19
  • 31
  • ok yeah I had been trying to use alarm for something else but I figured there would be a way to set a timeout for the entire script but I guess not.. I will look into alarm more.. thanks – Rick Aug 06 '10 at 20:14
  • 1
    It's best to avoid explicit use of `eval` and `$@`, as there are many subtle gotchas. Check out [Try::Tiny](http://search.cpan.org/perldoc?Try::Tiny) for one of many alternatives (this one is the most lightweight) (and when I refresh the page I see that Sinan used it in his answer) :D – Ether Aug 06 '10 at 20:24
  • 3
    Rick, you can set a timeout for the entire script -- just call `alarm` outside of an `eval` block. – mob Aug 06 '10 at 20:27
  • Rick, `alarm` generates a fatal exception. If you don't catch it with `eval` it will terminate your script. – daotoad Aug 07 '10 at 19:59