Говоря конкретно на py-filelock
Библиотека filelock
, используемая для удаления файлов блокировки в UNIX;это поведение было удалено с benediktschmitt/py-filelock#31
, что относится к flock (): удаление заблокированного файла без условия гонки? - где обсуждаются те же условия гонки, которые описаны в следующем разделеэтот ответ.
Почему общая практика отличается
Семантика операционной системы различна, поэтому в каждом случае уместны разные подходы.В UNIX вы можете удалить файл, даже когда есть открытый дескриптор, поэтому lockfiles нельзя удалять , иначе две программы могут считать, что они держат одну и ту же блокировку, хотя на самом деле они держат блокировки на совершенно разных inodeна которые в разные моменты времени ссылались под одним и тем же именем.
Напротив, семантика файловой системы по умолчанию в Windows делает невозможным удаление файла, когда у любой программы он открыт (даже если NTFS достаточно мощная, чтобыподдерживать его, это искусственно предотвращается для обратной совместимости с программами, разработанными с учетом ограничений FAT), поэтому в Windows безопасно удалить файл блокировки: если удаление проходит, это доказывает, что никто не удерживал блокировку (или даже находился в процессе открытия).файл, чтобы позже получить на него блокировку).
Пример конкретной гонки
Чтобы привести пример того, как разрешение открывать файлы без связи в UNIX делает удаление файлов блокировки опасным, рассмотрите возможностьследующая иллюстрация общего гусловие ace:
- Программа 1 создает и открывает файл A1 (под именем «A»), получая дескриптор файла, прикрепленный к индексу (объект, отражающий сам фактический файл, а не запись каталога, в которой он находитсяприкреплен к) для этого вновь созданного файла.
- Программа 1 запрашивает исключительную консультативную блокировку для этого дескриптора.Никакие другие процессы не имеют дескриптора для того же файла, поэтому его запрос на блокировку удовлетворяется.
- Программа 2 открывает файл A1, получая второй дескриптор файла для того же файла.
- Программа 2 запрашиваетэксклюзивный консультативный замок на этой ручке.Однако, поскольку программа A уже удерживает блокировку, запрос блокирует, то есть программа ожидает, когда операционная система вернет управление ей позже, когда блокировка может быть предоставлена.
- Программа 1 завершает процессы, для которых ей нужна была блокировка.
- Программа 1 использует системный вызов
unlink()
для удаления файла блокировки. (Для безопасности в UNIX просто оставьте этовыйти).Это не удаляет сам файл («inode») до тех пор, пока его не откроют никакие программы, но немедленно удаляет ссылку на этот файл из каталога, в котором он был ранее. - Программа 1 закрывает свой дескрипторна файл, таким образом освобождая свою блокировку.Индекс не удаляется, потому что Программа 2 по-прежнему содержит дескриптор.
- Программе 2 предоставляется блокировка, которую она ждала, для дескриптора файла (в теперь не связанном файле A1), который она открыла до удаленияи может возобновить выполнение.
- Программа 3 создает и открывает новый файл A2 (с новым и отличным индексом) с тем же именем «A» (который доступен, потому что индекс A1 больше не связан сэто имя), получая дескриптор файла на том же.
- Программа 3 запрашивает блокировку на дескриптор файла, которым она владеет. Это немедленно предоставляется, потому что A2 - это файл, отличный от A1, и все еще работающая Программа 2 удерживает блокировку A1, а не A2.Таким образом, мы получаем две программы - Программу 2 и Программу 3 - думающие, что они имеют одинаковую блокировку.
Следовательно, вышеприведенное иллюстрирует, как в UNIX удаление файлов блокировки позволяет создавать условия гонки, при которых блокировка может удерживаться двумя программами одновременно.