Когда вам нужно "END {закрыть STDOUT}" в Perl?

В бройлерной плите tchrists я обнаружил это явное закрытие STDOUT в блоке END.

END { close STDOUT }

Я знаю END и закрываю, но я пропускаю, почему это необходимо.

Когда вы начнете поиск по нему, найдите в perlfaq8 следующее:

Например, вы можете использовать это, чтобы сделать убедитесь, что ваша программа фильтрации завершить свою работу без заполнения диск:

END {
    close(STDOUT) || die "stdout close failed: $!";
}

и не понимают этого.: (

Может кто-нибудь объяснить (может быть, с некоторыми примерами кода):

  • почему и когда это необходимо
  • как и в каких случаях мой фильтр perl заполняет диск и т.д.
  • когда все становится не так без него...
  • и т.д.??

Ответы

Ответ 1

Многие системы реализуют "оптимистичные" файловые операции. Под этим я подразумеваю, что вызов, например, print, который должен добавить некоторые данные в файл, может успешно вернуться до фактического написания данных к файлу или даже до того, как достаточно свободного места зарезервировано на диске для успешной записи.

В этих случаях, если диск почти заполнен, все ваши отпечатки могут оказаться успешными, но когда пришло время закрыть файл и вывести его на диск, система понимает, что нет места. Затем вы получаете сообщение об ошибке при закрытии файла.

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

Все это может произойти в дескрипторе файла STDOUT, если он подключен к файлу, например. если ваш script запущен как:

perl script.pl > output.txt

Если данные, которые вы выводите, важны, и вам нужно знать, действительно ли все написано правильно, вы можете использовать оператор, который вы указали, чтобы обнаружить проблему. Например, во втором фрагменте script явно вызывает die, если close сообщает об ошибке; шаблон tchrist работает под use autodie, который автоматически вызывает die, если close не работает.

(Это не гарантирует, что данные хранятся постоянно на диске, хотя в них также играют другие факторы, но это хорошая индикация ошибки, т.е. если это закрывается, вы знаете, что у вас есть проблема.)

Ответ 2

Я считаю, что Мат ошибается.

Оба Perl и система имеют буферы. close вызывает сброс буферов Perl в систему. Это не обязательно приводит к тому, что буферы системы записываются на диск, как утверждал Мат. То, что делает fsync.

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

Другая вещь close - это сообщить о более ранних ошибках в попытках системы сбросить свои буферы на диск.