Re: Perl Alarm Not Working
by cdarke (Prior) on Dec 19, 2010 at 13:14 UTC
|
The following works for me: #!/usr/local/bin/perl
use warnings;
use strict;
sub do_program {
print "Please wait for a timeout....\n";
<STDIN>
}
my $timeout = 5;
eval {
local $SIG{ALRM} = sub { die "alarm\n" };
alarm $timeout;
&do_program(1, 100);
alarm 0;
};
if($@) {
print "$@<BR>\n";
}
Also on Linux 2.6.18.
You don't give details of what do_program is actually doing. If, as the name implies, it is running another process, then you should be aware that pending alarms are cleared in a child process. This is a UNIX feature, not anything to do with Perl. It then depends on how you are actually running the external process, and how you are waiting for it.
Proc::Background might help, it has a timeout feature.
Update: it occurs to me that, because of your use of <BR> in the print statement, you might be running under mod_perl. There are some notes concerning alarm here: http://perl.apache.org/docs/2.0/user/coding/coding.html. | [reply] [d/l] [select] |
Re: Perl Alarm Not Working
by ikegami (Patriarch) on Dec 19, 2010 at 05:04 UTC
|
What OS are you running, and what's do_program? | [reply] [d/l] |
|
Operation system is Linux 2.6.18
do_program is a program that abstracts site information from different domains.
The domains are stored in a MySql database, so the program will retrieve domains from the database, then abstract site information from these domains.
Jack
| [reply] |
Re: Perl Alarm Not Working
by ww (Archbishop) on Dec 19, 2010 at 13:28 UTC
|
Still need more detail about &do_program(1, 100);. Is that (merely) a subroutine in the same script or is it a sub that calls an external program... or ??? IOW, show us the code of the sub.
Semi-irrelevant: The value in $@ is the error message from whatever you're calling in &do_program(1, 100);; it's not going to be populated the the case you describe.
| [reply] [d/l] [select] |
|
&do_program(1, 100); is a subroutine in the same script.
In a nutshell, calling the &do_program(1, 100), it will do the followings:
1) Connect to the MySql database
2) Retrive 100 domains beginning from row 1 for 100 rows in one of the tables.
3) Remote access each of the 100 domains using LWP::UserAgent
4) Then abstract the site(domain) page information
It generally takes about 2 minutes to complete all of the above steps 1 to 4.
(Notes: I've watched it ran many times, it took around that kind time to complete.)
I'm mainly trying to find out if the scripts in the eval { } will work or not.
They do not seem to work, because &do_program(1, 100) will continue to run from start to finish even though I set the alarm timeout variable, $timeout at different numbers
less than 120(2 minutes), e.g. $timeout=20, $timeout=10, $timeout=5... down to 1 second $timeout=1.
For some reason, there is no alarm signal generated in the eval {} block??
| [reply] |
|
As I said, your code works for me (in an eval block).
One possibility is that MySQL is itself changing the signal handling. Mr. Google brought up a few suggestions: http://forums.mysql.com/read.php?51,256433,256478#msg-256478 is typical, with some alternative code, but I would have thought this would be common.
The DBI provides the cancel operation on statement handles $sth->cancel() specifically for calling from alarm handlers. This implies that the database driver itself might be immune to SIGALRM and it is up to the Perl signal handler to cancel the operation.
| [reply] [d/l] |
|
|
|
|
- "there is no alarm signal generated in the eval {} block?? "
So, use debug or print statements to see if that's actually so... and, not just incidentally, time the sub at sub-second resolution (Time::HiRes, for example) or using (your favorite flavor of) profiler.
- The pseudo-code in your points 1) .. 4) does NOT inform me of any possible issues inside the sub. Code, as requested (unless long) * would do so.
* And if it's more than 10-15 lines, consider reducing it to a minimal form that still exhibits the problem. That serves two purposes: first, it may make something jump into view that clears up your question and, second, it makes it easier for us to help whilst our crystal balls are broken and psi blocked by DHS.
| [reply] |
|
My only guess is that the MySQL driver uses alarm internally, leaving it canceled.
Can you simulate the DB code for testing purposes?
| [reply] [d/l] |
|
Re: Perl Alarm Not Working
by BrowserUk (Patriarch) on Dec 19, 2010 at 21:11 UTC
|
With Deferred (or Safe) Signals enabled--the default since 5.8.something--there are (many) somethings that cannot be interrupted by SIGALRM.
Reading your later description of do_program(), it seems like that it is doing many, maybe even most, of those somethings.
You may find the use of Perl::Unsafe::Signals worth testing.
Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.
| [reply] [d/l] |
|
| [reply] |
|
C:\test>start /b perl -MIO::Socket
-E"$s=IO::Socket::INET->new(Listen=>1,LocalPort=>12345);$c=$s->accept;
+sleep 30"
C:\test>perl -MIO::Socket
-E"$s=IO::Socket::INET->new('localhost:12345');eval{alarm 10;<$s>};pri
+nt'here'"
here
Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.
| [reply] [d/l] |
|
|
|