Beefy Boxes and Bandwidth Generously Provided by pair Networks
There's more than one way to do things
 
PerlMonks  

Alternatives to Mixing Alarm and Sleep

by pileofrogs (Priest)
on Feb 19, 2010 at 23:34 UTC ( [id://824281]=perlquestion: print w/replies, xml ) Need Help??

pileofrogs has asked for the wisdom of the Perl Monks concerning the following question:

Greetings ye Monks.

I have a loop that sleeps at the end and I want to make the thing bail out if the whole loop takes too long. The obvious solution:

alarm 10 while ( ! $done ) { $done = is_it_done_yet(); sleep 1; }

... is bad because perlfunc says:

It is usually a mistake to intermix "alarm" and "sleep" calls. ("sleep" may be internally implemented in your system with "alarm")

So what's the "right" way to do this?

Do I want to fork off a watcher process? Is there a simpler way? If there isn't a simpler way, is there a good CPAN module that handles this?

For background: I'm writing an apache log rotater. I want to compress the files once apache has stopped writing to them, which is what is_it_done_yet() is analogous to. My script checks to see if it can start compressing by using lsof (Unix::Lsof) and compresses them using gzip if it can. If lsof or gzip wander off and never return, I want to have some way to abort the whole thing.

Thanks!
--Pileofrogs

Replies are listed 'Best First'.
Re: Alternatives to Mixing Alarm and Sleep
by ruzam (Curate) on Feb 20, 2010 at 01:39 UTC

    If you're looping with a sleep (instead of actually hanging on a blocking function to return) then I think you just want to just do away with the alarm all together and keep a loop counter.

    $loop_count = 10; while( ! $done and $loop_count-- ) { $done = is_it_done_yet(); sleep 1; }

    The alarm is more useful if you have to break out of a blocking function, in which case you probably wouldn't be using sleep anyway.

    Update...

    On re-read, it sounds like you don't want to get caught hanging on is_it_done_yet(). In which case I think you want to alarm this function separately in an eval.

    while( ! $done ) { eval { local $SIG{ALRM} = sub { die "alarm\n" }; alarm 10; $done = is_it_done_yet(); alarm 0; }; last if @$ and $@ eq "alarm\n"; # hit alarm timeout sleep 1; }
Re: Alternatives to Mixing Alarm and Sleep
by johngg (Canon) on Feb 20, 2010 at 00:21 UTC

    Perhaps you could use select?

    alarm 10; while ( ! $done ) { $done = is_it_done_yet(); select undef, undef, undef, 1.0; }

    I hope this is helpful.

    Cheers,

    JohnGG

Re: Alternatives to Mixing Alarm and Sleep
by zentara (Archbishop) on Feb 20, 2010 at 11:54 UTC
    is there a good CPAN module that handles this?

    Yes, they are called event-loop systems. See POE or Glib

    See Roll your own Event-loop for an example of Glib. POE comes with a cookbook of examples. You want to setup a timer.


    I'm not really a human, but I play one on earth.
    Old Perl Programmer Haiku

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://824281]
Approved by kennethk
Front-paged by kennethk
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others examining the Monastery: (5)
As of 2024-04-25 14:32 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found