oalders
oalders

Reputation: 5279

How to detect if Perl code is being run inside an eval?

I've got a module that uses an @INC hook and tries to install missing modules as they are used. I don't want this behaviour to fire inside an eval. My attempt to do this currently is:

return
    if ( ( $caller[3] && $caller[3] =~ m{eval} )
    || ( $caller[1] && $caller[1] =~ m{eval} ) );

That's the result of me messing around with the call stack in some experiments, but it's not catching everything, like this code in HTTP::Tinyish:

sub configure_backend {
    my($self, $backend) = @_;
    unless (exists $configured{$backend}) {
        $configured{$backend} =
          eval { require_module($backend); $backend->configure };
    }
    $configured{$backend};
}

sub require_module {
    local $_ = shift;
    s!::!/!g;
    require "$_.pm";
}

Maybe I just need to traverse every level of the call stack until I hit an eval or run out of levels. Is there a better or easier way for me to figure out whether or not code is being wrapped in an eval without traversing the call stack?


Post mortem on this question:

Upvotes: 7

Views: 284

Answers (3)

ysth
ysth

Reputation: 98388

Don't try to do this in reusable code. There are many reasons to be in an eval and not want this kind of action at a distance change.

Upvotes: 3

mob
mob

Reputation: 118605

Carp::longmess traverses the stack for you in one call, if that makes things easier

return if Carp::longmess =~ m{^\s+eval }m

Upvotes: 5

Schwern
Schwern

Reputation: 164769

If $^S is true, the code is inside an eval.

sub foo { print $^S }
eval { foo() };  # 1
foo();           # 0

Upvotes: 5

Related Questions