perlexceptionevaldie

where is perl eval "...propagated" documented


In the following code, eval checks whether an expression is valid. It captures an exception, and my code prints out the exception, without the code dying at that point. So far, so good.

But when a die; expression is subsequently encountered, the exception text is printed out again, without my asking for it, with the addition of a ...propagated message, giving the line number of the die; command. But at this point, the exception text is inappropriate and confusing. It seems that perl holds onto the eval error message, or exception message, until we reach a die;.

Below the code posted below are two workarounds, either of which makes the behavior go away.

Where is this particular behavior documented? What's the thinking behind it?

#!/usr/bin/perl
use strict; use warnings;
my $str=q/(d/;
my $rgx;
eval{$rgx=qr/$str/};
if(length $@)
{
   print join('', 'qr/', $str, '/ does not compile: ',"\n", $@, );
}
print "Got past eval. But next, at 'die;', it will print an error message that no longer pertains.\n";
die;

Workaround (1). Give die; a nonempty string:

#!/usr/bin/perl
use strict; use warnings;
my $str=q/(d/;
my $rgx;
eval{$rgx=qr/$str/};
if(length $@)
{
   print join('', 'qr/', $str, '/ does not compile: ',"\n", $@, );
}
print "Got past eval. Next, the nonempty string in die ' '; flushes out the inappropriate exception message.\n";
die ' ';

Workaround (2). Execute another eval which does not find a syntax error:

#!/usr/bin/perl
use strict; use warnings;
my $str=q/(d/;
my $rgx;
eval{$rgx=qr/$str/};
if(length $@)
{
    print join('', 'qr/', $str, '/ does not compile: ',"\n", $@, );
}
print "got past eval\n";
$str=0;
eval{$rgx=qr/$str/};
die;


Solution

  • It's fairly logical behavior, I'd say, with die used without arguments. What is it supposed to do?

    Documented in die

    If LIST was empty or made an empty string, and $@ already contains an exception value (typically from a previous eval), then that value is reused after appending "\t...propagated". This is useful for propagating exceptions:

    eval { ... };
    die unless $@ =~ /Expected exception/;
    

    [...]

    So issuing an unrelated die without any arguments gets mixed up in this facility.