После scoped `no autodie` программа не работает на` *STDOUT`

Эта программа

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";

прерывается с

Неопределенная подпрограмма вызывается в строке 10 problem_no_autodie.pl.

Чтобы переформулировать комментарий в коде: если есть use autodie;заявление сначала тогда все хорошо. (Все хорошо только с use autodie; тоже.) Любопытно, что в одном объеме с no autodieзаявление Я тоже не вижу таких проблем; только код за пределами его области действия не работает! Что-то вроде анти-прицела, а?

Если это ограничено no autodieприходит после использования *STDOUTтогда все снова хорошо. Дальнейшее использование *STDOUT, после (в области видимости) no autodie, программа не работает.

Существует Гоча упоминается в документации, которая вовлекает barewords (который я не полностью понимаю), и программа действительно терпит неудачу с STDOUT - но у меня это как *STDOUT.

Получается, что *STDOUT рассматривается как подписка пользователя, но я не понимаю ни этого, ни того, как autodieтерпит поражение. (Утечка области видимости упоминается как ошибка в некоторых версиях, но, по-видимому, не имеющим отношения к делу.) И здесь есть практическая проблема.

Я не использую autodieв моем коде. Но рассмотрим этот саб, который я использую

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

Это законно open потерпеть неудачу, поэтому мы должны отключить autodieв этой области, если он есть у пользователя сабвуфера. Тогда при каких обстоятельствах описанное поведение может навредить?

Меня озадачивает такой эффект no autodieи по его утечке за рамки, и по всем их странным деталям. Но реальная проблема заключается в том, что я не уверен, как защитить код, использующий библиотеку, подобную той, что приведена выше, от такого поведения, поскольку я этого не понимаю. Есть идеи?

Я вижу это в разделах 5.16.3 (система), 5.26.2 и 5.30.0 (perlbrew) на CentOS 7.8

Я не вижу такого поведения в версии 5.32.0; нет сбоев.


В ... or die $! проверьте, что идет с open не имеет никакого значения, поэтому для простоты это не показано.

1 ответ

Решение

Эта ошибка появилась в autodie 2.24 и исправлена ​​в 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 отсутствует на CPAN.)

Чтобы защититься от этой проблемы, добавьте зависимость от autodie 2.30 или выше.

Другие вопросы по тегам