in reply to Re: Perl Alarm Not Working
in thread Perl Alarm Not Working

&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??

Replies are listed 'Best First'.
Re^3: Perl Alarm Not Working
by cdarke (Prior) on Dec 19, 2010 at 17:22 UTC
    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.
      You have something there that MySql is immune to SIGALRM.

      Here's another test script I wrote to test SIGALRM in a script running MySql:

      #!/usr/bin/perl require 'myconfigure.cgi'; $timeout = 5; use DBI; $keywords = "Whether rocking natural-curls, a-short"; print "Content-type: text/html\n\n"; sub do_search { $time1 = time; $dbh=DBI->connect("dbi:mysql:$database:localhost","$username","$pa +ssword"); $keywords_quoted = $dbh ->quote ($keywords); $query="SELECT count(*) FROM $websites_table WHERE MATCH(title) AG +AINST ($keywords_quoted)"; $sth=$dbh->prepare(qq{$query}); $sth->execute(); $total_count = $sth->fetchrow_array (); $sth->finish; $dbh->disconnect ||die("Couldn't disconnect to database!\n"); $time2 = time; $time_ran = $time2 - $time1; } eval { local $SIG{ALRM} = sub { die "alarm\n" }; alarm $timeout; &do_search; alarm 0; }; if($@) { $time2 = time; $time_ran = $time2 - $time1; print "$@, Time Ran: $time_ran, Total Count: $total_count\n"; exit; } print "Time Ran: $time_ran, Total Count: $total_count\n"; exit;

      Above script basically do a search for the number of matches of $keywords in $websites_table. I've used a timeout of 5 seconds( $timeout = 5;) to limit the time of search, i.e. exit if search takes more than 5 seconds.

      When it timeouts by the eval{} block, it will indicate how much time the script has ran as shown by the variable $time_ran in the if($@) loop.

      But I'm getting funny results when it timeout. It overshoots the timeout limit of 5 sec condiderably. In one instance, I got a value of $time_ran = 18.

      How do I fix this problem?
        There's two different issues at play:
        • Calls to C code (e.g. calls to the db driver) are not interruptible.
        • DBD::mysql might clear the alarm.

        When it takes longer than the timeout, does it say "alarm" and ", Time Ran" or just "Time Ran"? If it's the former, you have crazy long database calls and should look at fixing that. If it's the latter, DBD::mysql is probably using alarm itself so you're pre-empted from using it yourself.

Re^3: Perl Alarm Not Working
by ww (Archbishop) on Dec 19, 2010 at 18:59 UTC
    • "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.

Re^3: Perl Alarm Not Working
by ikegami (Patriarch) on Dec 19, 2010 at 20:34 UTC

    My only guess is that the MySQL driver uses alarm internally, leaving it canceled.

    Can you simulate the DB code for testing purposes?