После определения области `no autodie` программа умирает при `* STDOUT`

#perl #scope #autodie

#perl #область действия #автозапуск

Вопрос:

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

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

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

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

say "$$ done";
  

прерывается с помощью

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

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

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

В документах упоминается ошибка, которая включает в себя простые слова (которые я не до конца понимаю), и программа действительно завершается с STDOUT ошибкой — но у меня это как *STDOUT .

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

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

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

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

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

Я вижу это в 5.16.3 (system), 5.26.2 и 5.30.0 (perlbrew) на CentOS 7.8

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


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

Комментарии:

1. Я не получаю никаких ошибок с 5.26.1 (system) или 5.32.0 (perlbrew) в системе Ubuntu 18.04.

2. @Shawn Интересно. В частности, тот факт, что две версии, в которых она не работает для меня, заключают в скобки ту, в которой она не работает для вас. Я установил 5.32.0 под perlbrew — и для этого он не работает! Отредактированный вопрос соответствующим образом. Итак, мы кое в чем согласны 🙂 Спасибо, что проверили это.

3. @Shawn Я установил 5.26.1 для тестирования, учитывая ответ ikegami, и программа не работает под ним для меня! Возможно, ваша Ubuntu исправила (или обновила версию) на 5.26.1?

Ответ №1:

Эта ошибка была введена в autodie 2.24 и исправлена в autodie 2.30.

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

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

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

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

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

(2.30 не найден в CPAN.)

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

Комментарии:

1. Спасибо. Вероятно, я не могу обновить определенный модуль в наших производственных системах (политики и т. Д.), Поэтому я буду использовать eval вместо no autodie .

2. @zdim Вы могли бы исправить проблемный сабвуфер. *Foo::is_atty = sub { ... }; завернутый в проверку версии (потому что это намного лучше, чем обновление модуля …)

3. Это заставило бы вызывающий код использовать только «разрешенную» версию autodie ? Хотя это правильный путь , я думаю, мне придется пройти его, учитывая, как и где библиотека может быть использована. Возвращается к моему непониманию того, что делает жук, и при каких обстоятельствах он может укусить. Но я думаю , что у меня это есть лишь в нескольких местах , так eval что вместо этого легко

4. ? Нет, это не заставит код использовать версию autodie, которая не установлена; это дало бы возможность вообще избежать использования autodie.