For Programmers: Free Programming Magazines  


Home > Archive > PERL Beginners > November 2005 > ALARM









You are viewing an archived Text-only version of the thread. To view this thread in it's original format and/or if you want to reply to this thread please [click here]

 

Author ALARM
Tom Allison

2005-11-22, 7:56 am

I figured out I can do this:

eval {
local $SIG{ALRM} = sub { warn("alarm\n") };
alarm 1;
for(my $j = 0; $j < 1_000_000, $j++) {
my $x = log(rand()*1000+1);
}
alarm 0;
};
if ( $@ ) {
carp "$@\n";
}

Which is very similar to the man pages.
But there are a few inconsistencies I'm trying to sort out.

First, I can't seem to get the statement from the manpages
die $@,"\n" unless $@ eq "alarm\n";
to work.

Second, I tried putting this into a for(){...} loop to attempt this 5
times. I can't seem to get it to do that. It goes through one loop and
then it just keeps doing the warn("alarm\n") without doing anything else.

Conceptually, I'm trying to do something and if it take too long, start
over again, retrying 5 times.

Unfortunately 'perl -d' really doesn't handle this very well.
John Doe

2005-11-22, 7:56 am

Tom Allison am Dienstag, 22. November 2005 12.24:
> I figured out I can do this:
>
> eval {
> local $SIG{ALRM} = sub { warn("alarm\n") };
> alarm 1;
> for(my $j = 0; $j < 1_000_000, $j++) {
> my $x = log(rand()*1000+1);
> }
> alarm 0;
> };
> if ( $@ ) {
> carp "$@\n";
> }
>
> Which is very similar to the man pages.
> But there are a few inconsistencies I'm trying to sort out.


The syntax is incorrect, see the comma in the for-().

Your sighandler uses warn instead of die (die puts the output into $@, warn to
STDERR)

> First, I can't seem to get the statement from the manpages
> die $@,"\n" unless $@ eq "alarm\n";
> to work.


Thats (i guess) because of the warn above.

> Second, I tried putting this into a for(){...} loop to attempt this 5
> times. I can't seem to get it to do that. It goes through one loop and
> then it just keeps doing the warn("alarm\n") without doing anything else.


Try:

use strict;
use warnings;
eval {
local $SIG{ALRM} = sub { die 'Alarm' }; # <<<<<<
alarm 1;
for(my $j = 0; $j < 1_000_000; $j++) { # <<<<<<<
my $x = log(rand()*1000+1);
die;
warn "in for $x" unless $j / 100;
}
alarm 0;
};
if ( $@ ) {
warn "DIED ", ($@=~/^Alarm/) ? 'alarm' : 'no alarm'; # <<<
}


> Conceptually, I'm trying to do something and if it take too long, start
> over again, retrying 5 times.


I think this should be ok with corrected syntax
(maybe I overlooked something)

hth,

joe
Tom Allison

2005-11-22, 6:57 pm

John Doe wrote:
> Tom Allison am Dienstag, 22. November 2005 12.24:
>
>
>
> The syntax is incorrect, see the comma in the for-().
>


I didn't copy it correctly, you are right about the syntax.
I also changed the warn to die.
I can get this to work in my test script.

Now, I've replaced the 'for(my $j = 0....}' loop with the real deal and
it's just not working at all.

The real deal is more like this (I'm not posting all the code because it
might be boring)

eval {
local $SIG{ALRM} = sub { die "alarm\n" };
alarm 60;
my $ref = fetchdata($sql, $db);
alarm 0'
};
.....

and fetchdata() is a function in a module.
This function is basically a wrapper around DBI:

sub fetchdata {
my ($sql, $db) = @_;
my $dbh = get_dbh($db) or die $@; # another function within this
module
my $ref = $dbh->fetchall_arrayref($sql) or die $@;
return $ref;
}

----

I didn't write everything here perfectly so if there are syntax erros
please forgive me. But I'm not sure how these ALRM signals behave with
all these subroutine calls.
I get one 'alarm' and then nothing, the sql runs for a long time. I'm
intentially trying to test it to make sure it will 'alarm' more than
once.. The problem is the database server gets overloaded so I want to
try, wait, try, wait, try, die with each wait period being on the order
of an hour. It would be convenient to do this if I could.

The alternative would be to run two shell scripts. The first to create
a pidfile and the second to run only if that pidfile exists. Successful
completion of the program would remove the pidfile.

But that's not as '' or very perl-ish. I was hoping to be able to
use the alarm.
Purl Gurl

2005-11-22, 6:57 pm

John Doe wrote:

(snipped)
[color=darkred]
> But I'm not sure how these ALRM signals behave with
> all these subroutine calls.


I am not all that sure of what you are doing, your code examples
are changing periodically. Nonetheless, I can add some comments
about alarm which might help you. My comments are based on
extensive testing and discussion of alarm in another group, over
the years.

Use of alarm cannot be wrapped in a loop, in an iteration device,
a subroutine or any devices of a similar nature. Nor you can pass
signals out of such devices to trigger alarm.

At all times alarm must remain global and perfectly visible to
your program and to your system.

You may run a Google search on comp.lang.perl.misc with
keyterms related to alarm. You will find lots of articles which
discuss myriad problems working with alarm, many of which
are related to specific Perl versions and select platforms.

Perhaps in those articles you will find useful information.

Purl Gurl
John Doe

2005-11-22, 6:57 pm

Tom Allison am Dienstag, 22. November 2005 20.59:
> John Doe wrote:
>
> I didn't copy it correctly, you are right about the syntax.
> I also changed the warn to die.
> I can get this to work in my test script.


Hi Tom

I must admit that I'm not an all-day user of sigs. That might be one of the
reasons that I can't give you the answer, and there will be one from one of
the gurus here I guess.

> Now, I've replaced the 'for(my $j = 0....}' loop with the real deal and
> it's just not working at all.


What's the replacement? Fairly the big deal from below (it's not a loop).
What are the errors?

> The real deal is more like this (I'm not posting all the code because it
> might be boring)
>
> eval {
> local $SIG{ALRM} = sub { die "alarm\n" };
> alarm 60;
> my $ref = fetchdata($sql, $db);
> alarm 0'
> };
> ....
>
> and fetchdata() is a function in a module.
> This function is basically a wrapper around DBI:
>
> sub fetchdata {
> my ($sql, $db) = @_;
> my $dbh = get_dbh($db) or die $@; # another function within this
> module
> my $ref = $dbh->fetchall_arrayref($sql) or die $@;
> return $ref;
> }
>
> ----
>
> I didn't write everything here perfectly so if there are syntax erros
> please forgive me. But I'm not sure how these ALRM signals behave with
> all these subroutine calls.


In the example above, the alarm will trigger die and the program control gets
back to the code after the eval{}; the subs get interrupted, but I don't know
the gory details about the exact interruption point etc.

> I get one 'alarm' and then nothing, the sql runs for a long time. I'm
> intentially trying to test it to make sure it will 'alarm' more than
> once..


Not quite shure what you mean.
[Could it be that your system's signal handlers get lost between invocations?]

> The problem is the database server gets overloaded so I want to
> try, wait, try, wait, try, die with each wait period being on the order
> of an hour. It would be convenient to do this if I could.


Sounds like much, one hour! I'm not experienced with big databases, but is
there no possibility to tune the server a bit? How can it be useful with
waiting periods up to 1 hour?

> The alternative would be to run two shell scripts. The first to create
> a pidfile and the second to run only if that pidfile exists. Successful
> completion of the program would remove the pidfile.
>
> But that's not as '' or very perl-ish. I was hoping to be able to
> use the alarm.


One of the gurus surely has an IPC or whatever solution :-)

Sorry for not providing more help.

joe
Sponsored Links







Also available: Server administration forum archive | Web Design forum archive | Software forum archive | Hardware reviews archive

Copyright 2008 codecomments.com