Control flow

eval#

Run a piece of Perl code with any fatal error trapped instead of killing the program.

eval is Perl’s exception-catching mechanism and its runtime code-loader in one. It comes in two real forms: block eval (eval { ... }), which catches exceptions thrown by already-compiled code, and string eval (eval EXPR), which compiles and runs a string of Perl source at runtime. Either way, a die that would otherwise terminate the program becomes an assignment to $@ and a normal return.

Synopsis#

eval BLOCK                  # catch exceptions in compiled code
eval EXPR                   # compile and run source at runtime
eval                        # short for: eval $_

What you get back#

The value of the last expression evaluated inside the mini-program, or the value handed to an explicit return. The evaluation happens in the same context as the surrounding eval — void, scalar, or list — so wantarray inside an eval reports the caller’s context, not “some eval context.”

If anything inside raises an exception (die, a division by zero, a string-eval syntax error, any other trappable fatal), eval returns undef in scalar context and the empty list in list context, and the exception lands in $@:

my $n = eval { risky() };   # undef on failure, $@ holds the error
if ($@) { ... }

On success, $@ is set to the empty string. Every completed eval touches $@ — there is no “leave it alone” option. A control-flow operator that bypasses the normal exit (last, goto out of the block) can leave $@ unchanged, which is a corner case rather than a feature to rely on.

Global state it touches#

  • $@ — written on every normal exit of the eval: the thrown exception on failure, the empty string on success. Read to determine whether the eval caught something.

  • $^S — reflects whether Perl is currently inside an eval (or try). undef during parsing, true while executing inside an eval/try block, false at the top level. Read primarily by $SIG{__DIE__} handlers that want to act differently for caught vs. uncaught exceptions.

  • $SIG{__DIE__} — fires on every die, including those that an enclosing eval is about to catch. Use local $SIG{__DIE__} inside an eval to suppress a globally installed hook for the duration of the trap.

  • $SIG{__WARN__} — unaffected by eval. Warnings emitted inside the block still go through the normal warning path; eval does not redirect them into $@.

  • $_ — the source of the no-argument form (eval with nothing after it is exactly eval $_).

Block eval vs. string eval#

The two forms look similar but do very different things.

  • Block eval (eval { ... }) is parsed and compiled together with the surrounding program. At runtime it is just a marker that says “catch any die thrown from inside this block.” Because the code is already compiled, block eval is cheap and safe — the compiler already checked it for syntax errors. This is the form to reach for whenever the goal is exception handling.

  • String eval (eval EXPR) evaluates EXPR in scalar context, then parses and executes the resulting string as if it were a block in the lexical scope of the surrounding code. The parse happens every time the eval is reached. A syntax error in the string becomes a runtime $@, not a compile-time failure of the enclosing program. This is the form for loading code decided at runtime — optional features, user-supplied expressions, dynamically constructed subs — and it carries the costs and hazards that implies.

Both forms run in the lexical scope of the surrounding code: outer my variables are visible, and package variable assignments, subroutine definitions, and format definitions made inside the eval persist after it returns.

The $@ contract#

After an eval completes normally, $@ is always one of:

  • The empty string — the block ran to completion with no exception.

  • A string ending in a newline — a die "message\n" or a string exception the callee already terminated.

  • A string with appended location (... at FILE line N.\n) — a die "message" without a trailing newline, or a runtime error Perl itself raised.

  • A reference, typically a blessed exception object — die called with a reference.

Check $@ immediately after the eval and nowhere else. Any method call, ref test, isa check, or regex match done during handling can itself invoke an eval internally (for instance, during autoloading or overload resolution) and overwrite $@ before you finish inspecting it. Copy into a lexical first:

eval { work() };
if (my $err = $@) {         # safe snapshot
    if (ref $err && $err->isa('MyApp::Error')) { handle($err) }
    else                                         { die $err      }
}

Nested eval and local $@#

The outer eval sees whatever $@ holds when the outer block finishes — not what it held partway through. If inner code has its own eval, that inner eval sets $@ (to the empty string on success), which can clobber an error the outer code wanted to preserve. The guard is local $@ around the inner work:

eval {
    # ... some work that might fail ...
    {
        local $@;           # shield outer $@
        eval { optional_step() };
        # ignore whatever optional_step did to $@
    }
    die "still needed\n" if $condition;
};
warn "outer caught: $@" if $@;

Before Perl 5.14, $@ was assigned before localized variables were restored, so code that wanted to filter errors had to stage the value through a temporary. On 5.14+ (which 5.42 inherits) the order is fixed and the temporary is unnecessary.

String eval security#

String eval runs whatever is in the expression. If any part of that string came from untrusted input — a file, a network peer, a user form — the eval hands the attacker the full Perl interpreter. Rules of thumb:

  • Never pass user input through eval EXPR unmodified. “It’s only a number” is not a safeguard — "1; system 'rm -rf /'" is also only a string.

  • If runtime-chosen code is genuinely needed, constrain the input against a strict allow-list before interpolation, and prefer data-driven dispatch (a hash of coderefs) over generating source.

  • Floating-point values interpolated into source are fragile. Under use locale the decimal separator may not be a dot, and values like "NaN" or "Infinity" stringify to letters that the parser reads as barewords, not numbers.

  • Source filters activated inside a string eval leak out into the surrounding file scope (unless evalbytes is used). This is a long-standing quirk, not a feature.

Block eval has none of these problems — the code was compiled with the rest of the program.

BEGIN inside string eval#

BEGIN { ... } blocks embedded in a string eval execute immediately, before the rest of the eval’d code runs, matching their behaviour in a normal compilation unit. Set ${^MAX_NESTED_EVAL_BEGIN_BLOCKS} to 0 to make any embedded BEGIN throw instead:

local ${^MAX_NESTED_EVAL_BEGIN_BLOCKS} = 0;
eval $untrusted;            # any BEGIN inside $untrusted dies

This does not make a string eval safe — it only removes one specific attack on compile-time side effects.

try/catch#

Under use feature 'try' (stable since 5.40, available in 5.42), the try/catch/finally construct provides dedicated exception-handling syntax:

use feature 'try';

try {
    risky();
}
catch ($e) {
    warn "caught: $e";
}
finally {
    cleanup();
}

Differences from eval { ... }; if ($@) { ... }:

  • The caught value is bound to a fresh lexical $e (or whatever name is given), not to $@. No need for the my $err = $@ snapshot dance.

  • $@ is not set as a side effect — the try block has no global after-effect on it.

  • try is not itself a loop, but control-flow operators behave analogously to eval BLOCK: return inside try returns from the enclosing sub, and next/last/redo target an outer loop.

  • finally runs on every exit path and cannot itself use return/next/last/redo. It is marked experimental in 5.42 and emits a warning under experimental::try.

Reach for try/catch in new code. The eval-plus-$@ idiom remains correct and is still the right tool whenever the surrounding code must run on older Perls or must not require the feature guard.

Examples#

Trap a runtime error and keep going:

my $q = eval { $x / $y };
if ($@) { warn "division failed: $@"; $q = 0 }

Detect whether a feature is available without aborting at startup:

my $have_socket = eval { socket(my $s, PF_INET, SOCK_STREAM, 0); 1 };
die "no sockets on this build" unless $have_socket;

Load a module whose absence should be tolerated:

my $json = eval { require JSON::XS; JSON::XS->new } //
           do { require JSON::PP; JSON::PP->new };

Catch a blessed exception, re-throw anything else:

eval {
    parse($input);
};
if (my $err = $@) {
    if (ref($err) && $err->isa('MyApp::ParseError')) {
        report($err);
    }
    else {
        die $err;
    }
}

Nested eval with local $@ so an inner optional step does not erase an outer diagnostic:

eval {
    do_main_work();
    { local $@; eval { maybe_cleanup() } }   # ignore cleanup errors
    die "main still failed\n" if $something_else_wrong;
};
warn $@ if $@;

Suppress a globally installed $SIG{__DIE__} hook for the duration of a private trap:

eval {
    local $SIG{__DIE__};            # don't trigger hooks while we probe
    $answer = $x / $y;
};
warn $@ if $@;

A $SIG{__DIE__} hook that logs only uncaught exceptions, using $^S to tell the two cases apart:

$SIG{__DIE__} = sub {
    return if $^S;              # inside eval/try — let it propagate
    log_fatal(@_);              # top level — record before exit
};

Runtime-built dispatch (string eval used deliberately, input is not user-supplied):

for my $op (qw(add sub mul div)) {
    eval "sub ${op}_of { \$_[0] "
       . { add=>'+', sub=>'-', mul=>'*', div=>'/' }->{$op}
       . " \$_[1] }";
    die $@ if $@;
}

Edge cases#

  • No argumenteval; is eval $_. Rarely what you want; write eval { ... } or eval EXPR explicitly.

  • Final semicolon — may be omitted from the end of EXPR or BLOCK. eval "1+2" and eval "1+2;" are equivalent.

  • eval BLOCK is not a loopnext, last, and redo cannot leave or restart the block. They look for an enclosing loop and will croak if there is none.

  • return inside eval BLOCK returns from the enclosing subroutine, not from the eval — the eval block is not a function body. To produce a value from the block, put the value as the final expression.

  • Warnings are not trapped. warn inside an eval still writes to STDERR. Route them into $@ only if you set $SIG{__WARN__} to do so yourself.

  • Control flow out of eval — a goto, last, or next that jumps out of the block skips the normal eval exit and therefore may leave $@ untouched. Do not build logic that depends on this.

  • Quotes on EXPReval $x vs. eval "$x" behave identically: both run the code contained in $x. The double quotes add visual noise, not semantics.

  • eval '$x' vs. eval { $x } — both return the value of $x. The block form is compiled with the surrounding program; prefer it unless the code genuinely needs to be constructed at runtime.

  • eval '' inside the DB package — does not see the usual surrounding lexical scope but the scope of the first non-DB caller. Only debugger authors hit this.

  • XS load failures — some binary-interface problems during require of an XS module are fatal even inside eval, unless $ENV{PERL_DL_NONLAZY} is set. Version skew between the running interpreter and a pre-built .so is the common case. pperl does not load XS; the caveat applies when eval’d code delegates loading to a classic perl5.

Differences from upstream#

Fully compatible with upstream Perl 5.42.

See also#

  • die — the counterpart: throws the exception that eval catches. The trailing-newline rule on the message shapes what lands in $@.

  • dodo FILE reads and evaluates a file the way string eval reads and evaluates a string; useful for configuration files written in Perl.

  • return — inside eval BLOCK returns from the enclosing sub, not from the block; use a trailing expression to hand a value back from the eval itself.

  • require — commonly wrapped in eval to probe for optional modules without aborting at compile time.

  • evalbytes — string eval that treats its argument as a byte string and allows source filters to work normally; use when byte-level semantics matter.

  • $@ — where a caught exception lands, cleared to the empty string on successful eval.

  • $^S — tells $SIG{__DIE__} and $SIG{__WARN__} handlers whether an eval or try is currently active.

  • $SIG{__DIE__} — pre-throw hook; fires even for exceptions an enclosing eval is about to catch, which is the usual reason to local-ize it for the duration of a trap.