foreach $j (@j) {
alarm 2;
# ^ You shouldn't set an alarm out of the scope where you eval the time out and localize $SIG{ALRM};
local $SIG{ALRM} = sub { die "timed out" };
# ^ This localization should be inside an eval block so you can catch the alarm.
eval { callfc() };
# ^ Here, you are only catching errors from your function, not from a timeout
next if $@ and $@ =~ /^timed out$/;
# ^ You are checking for the exact string "timed out", but you should have /^timed out/ (without $ at the end), or, "timed out\n" in both places (including the new-line character) because otherwise the message will include traces information from "die"
}
####
foreach $j (@j) {
print "Next Loop $j \n";
eval {
local $SIG{ALRM} = sub { die "Alarm\n"; };
alarm(2);
&callfc();
};
# ^ This is much better, you localize $SIG{ALRM} inside eval, and you are also using
# the new-line character in the message (and that's why it works (partially))
# In here, you should have called alarm(0) to cancel the alarm.
# It doesn't matter if you are out of the eval block, the alarm continues to run
# and you eventually can have an uncatched "timeout" while being on a different
# part of your flow. You must call alarm(0) after your eval block (not from inside
# because it can die for a different cause too and never get to the alarm(0) line).
# So, I added it here:
alarm 0;
if ($@) {
die unless $@ eq "Alarm\n";
# ^ You should send the error to the die too so you know what went wrong,
# like this: die $@ unless $@ eq "Alarm\n";
# But yes, you would catch a timeout here (if alarm 0 was present too above).
} else {
print "Didnt\n";
}
}
print "I am continuing with the code\n";
# ^ Yeah... except if you didn't set alarm(0) above, and your script continues
# to run and take longer than the alarm to complete, you'll eventually have an
# error stating "Terminating on signal SIGALRM(14)" and wonder why that happened.
####
# First, the thing you want to timeout must be inside of an eval block:
eval {
# Second, localize the signal handling and set alarm to the desired timeout limit:
$SIG{ALRM} = sub { die "timeout\n" };
alarm 10;
# Third, add the lines of code you specifically want to timeout:
do_something_here_that_can_timeout();
};
# Fourth: CANCEL the alarm immediately or you may have problems later!
# This should be AFTER the eval block, not inside the eval block:
alarm 0;
# Fifth: Check for errors to see if you had a timeout or something else:
if ($@ eq "timeout\n") {
# Do whaever you need if a timeout happened
handle_timeout();
} else {
# You had an actual error and not a timeout, so handle it:
handle_error($@); # or just: die $@
}