Каковы последствия не закрытия дескриптора каталога в Perl? - PullRequest
6 голосов
/ 10 сентября 2010

Я недавно унаследовал некоторый код, который написал кто-то другой.

Я обнаружил, что везде в коде, в котором каталог открывался для чтения, он никогда не закрывался, потому что у исходного разработчика была проблема с синтаксисом - он использовал функцию close, чтобы попытаться закрыть дескриптор каталогафункции closedir.

Код был примерно таким:

opendir( DIR, $dir ) or die "Cannot open $dir: $!\n";
@files = readdir( DIR );
close( DIR );

(что является еще одним хорошим замечанием в Perl Best Practices (стр. 208, 278) о проверке возврата).функции close. Если в этом случае было проверено возвращение close, то с ошибкой "Bad file number" произойдет сбой.)

С тех пор я изменил это значение на closedir, ноэто заставило меня задуматься: так как дескриптор каталога никогда не был закрыт, каковы отрицательные последствия для того, чтобы держать дескриптор каталога открытым в течение длительного времени?

Эта программа больше (3500 строк кода), работает дляwhile (5-10 минут), и несколько экземпляров этой программы работают одновременно.В случае этого каталога в приведенном выше примере $dir является одинаковым значением для всех экземпляров.Если 10 экземпляров этой программы выполнялись одновременно, все они держали дескриптор открытого каталога в одном и том же каталоге в течение 5 минут или дольше.Я уверен, что Perl автоматически закрывает дескриптор каталога, когда программа завершает свою работу, но в соответствии с рекомендациями закройте его как можно скорее.

Для меня более очевидно, что если оставить дескрипторы файлов открытыми, это может вызвать проблемы (особеннодля файловых дескрипторов, которые открыты для записи), но какие плохие вещи могут произойти, если не закрыть дескриптор каталога?

Причина, по которой я спрашиваю, состоит в том, что было странное обстоятельство, когда эта программа пыталась создатьфайл (в каталоге, определенном $ dir выше).В имя файла встроен PID, поэтому вероятность того, что файл уже может быть там, меньше, но Perl не смог открыть файл для записи, поскольку он сказал, что он уже существует.Когда мы посмотрели в каталоге, этот файл не существует.Мне интересно, могут ли все дескрипторы открытого каталога в этом каталоге вызывать такую ​​проблему?

Я не уверен, что ОС имеет значение, но эта программа работает в AIX.

Заранее спасибо, и счастливой пятницы!

Ответы [ 3 ]

11 голосов
/ 10 сентября 2010

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

Если дескриптор каталога представлял собой локальную переменную, а не просто имя в стиле DIR, возможно, Perl убирает за вами. См. opendir , в котором говорится:

Открывает каталог с именем EXPR для обработки readdir, telldir, seekdir, rewinddir и closedir. Возвращает true в случае успеха. DIRHANDLE может быть выражением, значение которого может быть использовано как косвенный dirhandle, обычно это реальное имя dirhandle. Если DIRHANDLE - неопределенная скалярная переменная (или массив, или элемент хеша), переменной назначается ссылка на новый анонимный указатель. DIRHANDLE имеют свое собственное пространство имен, отдельное от FILEHANDLE.

8 голосов
/ 10 сентября 2010

Никаких радикальных последствий не будет.Будет очень небольшое увеличение использования памяти со стороны самого ядра, которое не может освободить итератор, который он использует внутри для циклического перемещения по списку записей каталога, и, вероятно, также со стороны perl.

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

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

 { # new scope
     opendir(my $handle, ...) or ...;
     ...
 } # implicit closedir happens here
7 голосов
/ 10 сентября 2010

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

Таким образом, вы будете тратить только дескрипторы (как Джонатанописывает) если 1. вы использовали дескриптор glob старого стиля, или 2. весь код написан в виде простого сценария без подпрограмм и других областей видимости.Используйте хорошие методы программирования, и случайных ошибок будет меньше:)

...