Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl-Sensitive Sunglasses

Builtin Watchdog for a sub (or block)

by PetaMem (Priest)
on Apr 28, 2002 at 14:22 UTC ( #162656=perlmeditation: print w/replies, xml ) Need Help??

Dear Monks,

for reasons that are far beyond the scope of this node (and far beyond my english abilities to explain), I feel that there is a functionality missing, that'd bring qualitative advantage for coding a certain class of problems: Cheating God(s of computer science). :-)

I will try to give a very rough overview of my thoughts and would be very happy if some of you would find this problem worthy for a meditation.

Gödel's Undecidability Theorem (see here for a short introduction) - for some a very very theoretical thing - can be applied to some very real programming problems one can encounter with Perl: the standard halting problem for Turing machines

Let's say, you have some code given. Untested by you (or others), unknown to you. Probably all you know is, that it runs. You - however - don't know how long it will take to run. It may very well be, that it will run into an endless loop. The aforementioned Theorem by Gödel and the mathematical proof of the standard halting problem by Turing brought R. PENROSE to the conclusion, that machines will always lack a "functionality" people have: a machine cannot decide if a problem has a solution or not therefore it may stick for infinite time on computing a solution for an unsolvable problem 'till hell freezes.

This is exactly where Perl comes in. Hard things are possible and impossible things are just hard. Let's say you'd have something like that:

sub cheatemall { my $givetime = shift; &InitMagicWatchdog($givetime,"Y"); # ... Do wild computations # ... If successfully computed return X # ... Return Y if computation ends, but the result is "false" }
Let's forget for a moment about this MagicWatchdog thingie. The Wild computation is just an regexp searching for a string. If it finds it, cheatemall returns X, if it doesn't find it, Y is returned.

Now: We give the MagicWatchdog - say - 5 seconds. If everything what comes after the InitMagicWatchdog needs more than 5 seconds until the sub is exited, well - then a magic Watchdog exits the cheatemall sub with a return value of "Y".

Shouldn't be too hard to implement? Thought so. But the magic Watchdog has to be some kind of supervision to the whole Perl program, because it has to exit cheatemall with return value Y even if the program is currently in some other subroutine (which was called doing the wild computetions).

And finally - my brave monks - my brain completedly lost track what should happen if cheatemall calls recursively itself. Then - hapily - I found it again: The subroutine calling cheatemall has to simply init its own MagicWatchdog. So yes, it should be possible to have these Magic Watchdogs spread across the whole source.

What do you say? Could one enhance Perl, so that it'd provide this functionality? I searched but only found these (seem not related):

Probably a Watchdog::Eval?

I'm excited about your input.


Replies are listed 'Best First'.
Re: Builtin Watchdog for a sub (or block)
by ehdonhon (Curate) on Apr 28, 2002 at 15:04 UTC
    sub cheatemall { my $givetime = shift; my $curtime = time(); my $oldalarm; my $oldsig = $SIG{ALRM}; $SIG{ALRM} = die ( 'ALARM' ); eval { $oldalarm = alarm( $givetime ); alarm( $oldalarm ) if ( $oldalarm < $givetime ); if ( ... ) { ## Apply your logic here. &reset_old_alarm( $curtime, $oldalarm ); return ...; ## return X } else { &reset_old_alarm( $curtime, $oldalarm ); return ...; ## return Y } }; ## We must have died out to get here. if ( $@ =~ /OLD ALARM/ ) { ## We got caught on a parent alarm. Re-create that ## alarm outside of our local eval block. kill( 'ALRM', $$); } elsif ( $@ =~ /ALARM/ ) { ## We alarmed out locally. return ...; ## return Y } else { ## Died for some other reason.. handle it here. } } sub reset_old_alarm { ## If you want to do object oriented stuff, you could ## make this be sub DESTROY so that this logic happens ## whenever your watchdog object goes out of scope. my ($curtime, $oldalarm) = @_; return alarm(0) if ( $oldalarm == 0); $oldalarm -= ( time() - $curtime ); die ( 'OLD ALARM' ) if ( $oldalarm <= 0 ); alarm($oldalarm); }

    UPDATE Fixed missing semicolon, thanx to Fatvamp
      alarm isn't (yet?) implemented on Win32. I'd argue that therefore this isn't a generic Perl solution, as it seems to be using OS specific functionality.
      (But I may be missing the point...)


        alarm isn't (yet?) implemented on Win32
        true. you can use Win32::Event, but the implementation's a little bit different than alarm.

        ~Particle *accelerates*

        I've posted a question on Ask Perl 6 on Use Perl about this: I think that it's wrong to call alarm and fork etc. features of the Perl language, because they are un- or partially- implemented for major platforms like Win32, and I'm hoping that Perl 6 will improve that!


      Yes - basically this goes to the right direction. However I had some problems with the code and am not able to solve them all.
      • I guess theres a ; missing after the eval block
      • It would be nice to have finer granularity than 1 sec. probably Timer::HiRes can do here something.
      • I wasn't able to find out what return value alarm has... somehow the code always boils out with an alarm.
      • Quite frankly - I don't understand the "parent alarm" thing.


        I guess theres a ; missing after the eval block

        Yes, thank you.

        Quite frankly - I don't understand the "parent alarm" thing.

        This was my answer to your request for an algorithm that could recursively call itself. Say $oldalarm is 3 and $givetime is 20. Even though cheatmail may have 20 seconds to complete its task, you know that somewhere higher in the callstack, you have another watchdog (which I refer to as a 'parent') that is expecting to be done one way or another in 3 seconds. Using this algorithm, you know that whichever watchdog is expecting to be done in 3 seconds will be the one to receive the alarm signal.

        • It would be nice to have finer granularity than 1 sec. probably Timer::HiRes can do here something.
        it's Time::HiRes (not Timer::HiRes.) if you don't want to add the overhead of a module, you can use select, as in select('','','',$time); instead.

        ~Particle *accelerates*

Log In?

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlmeditation [id://162656]
Approved by ar0n
Front-paged by grinder
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others cooling their heels in the Monastery: (7)
As of 2021-10-17 10:41 GMT
Find Nodes?
    Voting Booth?
    My first memorable Perl project was:

    Results (71 votes). Check out past polls.