Как мне запросить неблокирующую блокировку?
Почему File#flock Ruby не работает должным образом при отдельных попытках сделаны для блокировки файла? Блокировка файла в блоке не является правильным решением для этой проблемы, поскольку цель состоит в том, чтобы показать поведение блокировки при постоянных блокировках. Использование File#flock внутри блока снимает блокировку при выходе из блока, поэтому проблема не демонстрируется должным образом.
File#flock дает сбой по разным причинам, особенно при запросе неблокирующей блокировки. Ниже приведены некоторые примеры.
Неудачные примеры с File#flock
Бесконечное ожидание при использовании нескольких эксклюзивных блокировок, так как #flock не предоставляет способ истечения времени ожидания запроса на блокировку.
# First lock succeeds. f1 = File.open('foo', File::RDWR|File::CREAT, 0644) f1.flock(File::LOCK_EX) # => 0 # This never returns. f2 = File.open('foo', File::RDWR|File::CREAT, 0644) f2.flock(File::LOCK_EX)
Запрос на неблокирующую блокировку, когда файл монопольно заблокирован, приводит к исключению недопустимого аргумента.
f1 = File.open('foo', File::RDWR|File::CREAT, 0644) f1.flock(File::LOCK_EX) # => 0 f2 = File.open('foo', File::RDWR|File::CREAT, 0644) f2.flock(File::LOCK_NB) # => Errno::EINVAL: Invalid argument - foo
В документации сказано, что #flock «Блокирует или разблокирует файл в соответствии с locking_constant (логическим или из значений в таблице ниже)». Однако логическое ИЛИ вызывает
Errno::EINVAL
илиErrno::EBADF
в зависимости от платформы.f1 = File.open('foo', File::RDWR|File::CREAT, 0644) f1.flock(File::LOCK_EX) # => 0 f2 = File.open('foo', File::RDWR|File::CREAT, 0644) f2.flock(File::LOCK_NB || File::LOCK_EX) # => Errno::EINVAL: Invalid argument - foo
Предпочтение отдается собственному решению File#flock
Хотя можно использовать модуль тайм-аута, чтобы поднять Timeout::Error
, когда невозможно получить эксклюзивная блокировка, кажется, что File#flock должен решить эту проблему изначально. Итак, как на самом деле можно запросить эксклюзивную блокировку без блокировки?