in reply to Re^2: Where did $@ go?
in thread Where did $@ go?

As for your example, the core docs say that if eval completes without error, then $@ is guaranteed to be a null string
Even if that would be true, then
so you can write eval{...}; warn if $@;
doesn't follow.

For the second, you also need $@ to be true if the eval fails. Which doesn't need to be the case.

The problem is end-of-scope effects. eval { } is a block. Leaving the block, whether due to reaching the end, entering a return, or because the code dies, triggers end of scope effects. Which may cause more code to be executed (think DESTROY blocks). Which may clear, or set $@.

This is a known, but hard problem to solve (as one doesn't want to lose information carried in $@). There will be improvements in 5.14, IIRC.

Replies are listed 'Best First'.
Re^4: Where did $@ go?
by John M. Dlugosz (Monsignor) on Mar 21, 2011 at 12:06 UTC
    Re even if that were true:
    The eval docs state "If there was no error, $@ is guaranteed to be a null string."

      But that doesn't claim anything for the error situation. For example the following will (at least in Perl 5.12, and earlier versions) wipe $@ even though there is an error:

      sub Eater::DESTROY { eval { 1 }; }; my $ok = eval { my $foo = bless {}, 'Eater'; die "Booo!"; 1; }; warn "OK: [$ok]"; warn "\$\@: [$@]";
        I see. So the implied "and contains the die message or at least a \n" is messed up due to scope localization issues.

        Maybe that's what's "eating" the string in my case: some kind of destructor. And we should assume such things are happening in a fancy modern class-oriented system.

        But that doesn't explain why it's still "true". Maybe there is some magic involved and it is remembering that there is an uncaught exception even though the string is gone?

        So, are the various "fancy" try/catch systems inter-operable? I'm hoping they are all calling the same underlying class and pending-exception state system?

      "If there was no error, $@ is guaranteed to be a null string."
      Yeah, but it's useless, because the time frame where $@ is guaranteed to be a null string is less than the width of a semi-colon:

      sub DESTROY {$@ = "Hi"} eval {bless []}; say $@; __END__ Hi!
      No error, but between the finishing of the eval, and the first statement after the eval, the return value of eval is garbage collected, setting $@.