Beefy Boxes and Bandwidth Generously Provided by pair Networks
Think about Loose Coupling
 
PerlMonks  

Stopping code in eval

by Outaspace (Scribe)
on Jul 19, 2006 at 21:44 UTC ( #562445=perlquestion: print w/ replies, xml ) Need Help??
Outaspace has asked for the wisdom of the Perl Monks concerning the following question:

Dear all wise Monks of the Perl Code,

i have a question that is disturbing my inner confidence.

I want to eval a piece of code. So with an eval I can make sure that an error in the code dont let me script die. But what if the code enter an infinite loop? Is there any way (except modifying the code that is evaled) to stop it My script so far:
my $text = read_some_file_or_else(); eval $text; if ($@) { print "Error in eval: $@"; }

Now I want to give the text to be evaled a certain time to execute and break it of if it not ended after this time. Because the code can be anything (contains maybe an infinite loop or something else that can hang). I cant run it as a separate process, because it needs the context of my script. Anyone have any idea ?

Bless Perl and all other things that are good and righteous,

Andre

Comment on Stopping code in eval
Download Code
Re: Stopping code in eval
by samtregar (Abbot) on Jul 19, 2006 at 22:00 UTC
    It's possible to terminate some varieties of infinite looping with alarm():

    # setup an ALRM handler my $timed_out = 0; local $SIG{ALRM} = sub { die "Timed out!" }; # run some code for 10 seconds max eval { alarm 10; # let it run 10 seconds eval($code); die $@ if $@; }; # figure out if it got an alarm warn "Alarm rang!" if $@ and $@ =~ /Timed out!/;

    However, an infinitely running regex would probably not get interupted here due to Perl's new safe-signals implementation which only looks for new signals between op-codes.

    -sam

Re: Stopping code in eval
by Joost (Canon) on Jul 19, 2006 at 22:02 UTC
Re: Stopping code in eval
by rodion (Chaplain) on Jul 19, 2006 at 22:23 UTC
    At Perl docs on using ALRM for a timeout you will find exactly your problem addressed. If you prefer paper, a slightly longer discussion is in the camel book, Programming Perl, 3rd Ed., Ch. 16 starting in the secon section, "Signals", and continuing through "Timing out Slow Operations" both discussions are quite good.

    The link includes the following code (to wet your appetite), but don't just read it and mis out on the discussion. Follow the link, where the code is even chromacoded.

    eval { local $SIG{ALRM} = sub { die "alarm\n" }; # NB: \n required alarm $timeout; $nread = sysread SOCKET, $buffer, $size; alarm 0; }; if ($@) { die unless $@ eq "alarm\n"; # propagate unexpected errors # timed out } else { # didn't }
    Update: Added ", 3rd Ed."
Re: Stopping code in eval
by ikegami (Pope) on Jul 20, 2006 at 00:19 UTC
    To build on the preceeding replies, if a task must not exceed a time frame, delegate it to a child process. Kill the child if it doesn't complete the task in the aloted time.
Re: Stopping code in eval
by ioannis (Priest) on Jul 20, 2006 at 02:04 UTC
    Besides infinite loops, I presume that you also worry about memory allocations, and in general, allocation of resources. You need BSD::Resource to impose resource limits. (Depending on your operating system, you can limit consumption of some resources.)
Re: Stopping code in eval
by liz (Monsignor) on Jul 20, 2006 at 18:19 UTC
    If your only worry is about recursing too deeply, you could do something like this:
    eval { use warnings 'recursion'; local $SIG{__WARN__} = sub { die "Too deep" if $_[0] =~ m#^Deep re +cursion# }; # your code }; # check $@ if you want to here
    One of Perl's nice features is that it can actually output a warning when you're recursing too deeply (for whatever Perl considers to be "too deeply"). This trick changes that warning into an exit condition. This is a very simple case, if you need to keep the normal __WARN__ handler behaviour, things get a little more complicated.

    Hope this helps.

    Liz

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://562445]
Approved by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others drinking their drinks and smoking their pipes about the Monastery: (8)
As of 2014-09-02 23:04 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    My favorite cookbook is:










    Results (32 votes), past polls