Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

After scoped `no autodie` the program dies at `*STDOUT`

This program

use warnings;
use strict;
use feature qw(say);

{
    #use autodie;   # all good when this is uncommented
    no autodie;
}

open my $OLDSTD, '>&', *STDOUT;        #--> line 10 (program fails)
open *STDOUT, '>', 'stdout.out';

say "$$ done";

aborts with

Undefined subroutine called at problem_no_autodie.pl line 10.

To restate the comment in code: if there is a use autodie; statement first then all is well. (All is well with only use autodie; as well.) Curiously, in the same scope with no autodie statement I see no such problems either; only code outside of its scope fails! Kinda anti-scoping, eh?

If this scoped no autodie comes after the use of *STDOUT then it's all good again. Further use of *STDOUT, after (the scoped) no autodie, fails the program.

There is a Gotcha mentioned in docs that involves barewords (which I don't fully understand), and the program indeed fails with STDOUT -- but I have it as *STDOUT.

So it appears that *STDOUT is treated as a user's sub, but I don't understand that nor how the scope of autodie gets defeated. (Scope leakage is mentioned as a bug in some versions but in a seemingly unrelated way.) And there is a practical problem with this.

I don't use autodie in my code. But consider this sub, which I do use

sub isatty {
    no autodie;
    state $isatty = open(my $tty, '+<', '/dev/tty');
    return $isatty;
}

It is legitimate for that open to fail, so we have to disable autodie in that scope in case the user of the sub has it on. Then is the described behavior going to hurt? Under what circumstances?

I am puzzled by this effect of no autodie and by its leakage out of its scope, and by all their strange details. But the real concern is that I am not sure how to protect the code that uses a library like the one above against that behavior, since I don't understand it. Any ideas?

I see this under 5.16.3 (system), 5.26.2 and 5.30.0 (perlbrew) on CentOS 7.8

I do not see this behavior on 5.32.0; no failure there.


The ... or die $! check with open didn't make any difference so it's not shown for simplicity.

like image 886
zdim Avatar asked Oct 28 '25 08:10

zdim


1 Answers

This bug was introduced in autodie 2.24 and fixed in autodie 2.30.

$ ( cd ./autodie-2.23; perl Makefile.PL >&3; make >&3; perl -Mblib ../a.pl && echo ok ) 3>/dev/null
ok

$ ( cd ./autodie-2.24; perl Makefile.PL >&3; make >&3; perl -Mblib ../a.pl && echo ok ) 3>/dev/null
Undefined subroutine called at ../a.pl line 10.

$ ( cd ./autodie-2.29; perl Makefile.PL >&3; make >&3; perl -Mblib ../a.pl && echo ok ) 3>/dev/null
Undefined subroutine called at ../a.pl line 10.

$ ( cd ./autodie-2.30; perl Makefile.PL >&3; make >&3; perl -Mblib ../a.pl && echo ok ) 3>/dev/null
ok

$ ( cd ./autodie-2.31; perl Makefile.PL >&3; make >&3; perl -Mblib ../a.pl && echo ok ) 3>/dev/null
ok

(2.30 is not found on CPAN.)

To protect against this issue, add a dependency on autodie 2.30 or higher.

like image 147
ikegami Avatar answered Oct 29 '25 23:10

ikegami



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!