I just want to be able to set the program to run for a couple of hours (if need be) and then stop.
(additional emphasis by me)
I personally believe that for such prolonged times a solution along the lines of that suggested by L~R is best suited. Playing with alarm as duly suggested by ccn is more important in short lived situations in which finer control over time is needed and/or you need to timeout "no matter what" e.g. when running external processes:
#!/usr/bin/perl
use strict;
use warnings;
use 5.010;
use File::Basename;
my $pname; BEGIN { ($pname)=fileparse $0, qr/\.pl/i }
my $TIME = 10;
if (@ARGV) { # Working as a generic external program
sleep +(my $time=shift);
say "Slept $time seconds";
} else { # Example of timeout via alarm()
my ($msg, $timeout) = ("died in SIG ALRM", int rand 2*$TIME);
eval {
local $SIG{ALRM} = sub {die $msg};
warn "[$pname] Trying to collect output from external program.
+\n",
"(Setting timeout to $timeout seconds.)\n";
alarm($timeout);
chomp(my $output = qx/perl $0 $TIME/);
say "The output got from external program is: `$output'";
alarm(0);
};
if ($@ and $@ ~~ /\Q$msg/) {
warn "[$pname] Timed out!\n";
}
}
__END__
Incidentally, it is worth reminding that for finer control over (not necessarily) short times a precious module would be Time::HiRes, which is in core.