После этого ответа ограничиваем только один экземпляр скрипта php:
<?php $fp = fopen("/tmp/one.txt", "r+"); if (flock($fp, LOCK_EX)) { // do_something_lengthy(); // flock($fp, LOCK_UN); } else { echo "Couldn't get the lock!"; } fclose($fp); ?>
Мой вопрос в том, будет ли файл flock
'ed one.txt разблокирован, если процесс умирает посреди do_something_lengthy()
, т.е. перед вызовом flock($fp, LOCK_UN)
?
Согласно странице руководства flock()
которую использует PHP внутри, блокировка LOCK_UN
когда либо flock()
вызывается с LOCK_UN
либо когда дескриптор закрыт с помощью fclose()
.
После завершения сценария PHP или ОС закрывают дескрипторы открытых файлов, тем самым освобождая блокировки, которые у вас могут быть.
Из-за указанного поведения это commit (5.3) и этот (5.2) было сделано, чтобы больше не делать разблокировку в самом PHP.
Я сделал этот маленький скрипт, чтобы проверить его
header('Content-type:text/plain; charset=utf-8'); $dir = dirname(__FILE__); $file = $dir.'/testflock.lock'; $fh = fopen($file, 'w+'); $unlocked = flock($fh, LOCK_EX | LOCK_NB); echo 'Locked: '.$file.' ';var_dump(!$unlocked);echo PHP_EOL; if($unlocked){ sleep(10); throw new Exception(); }
и для меня потребовалось ОС, чтобы разблокировать файл примерно через 2-5 секунд после завершения скрипта, если он не выбрасывает исключение и до 2-5 секунд после остановки скрипта из-за брошенного исключения.
Имейте в виду, что с php 5.3.2 fclose($fh)
не разблокирует файл, и файл останется заблокированным, если вы не разблокируете его с помощью php, или вам придется дождаться, когда ОС разблокирует его, что, возможно, никогда не произойдет если есть какая-то ошибка (это случилось со мной)
Чтобы разблокировать файл:
flock($fh,LOCK_UN);
Чтобы закрыть дескриптор файла (будет вызываться автоматически, когда скрипт завершит выполнение)
fclose($fh);
Блокировка файла без LOCK_NB
заставит скрипт ждать, пока файл будет разблокирован.
Блокировка запускается автоматически, когда скрипт заканчивается. Однако вы должны выпустить его вручную и не полагаться на автоматический сбой. Лучше поймать любое исключение, обработать его и отпустить блокировку. См. Официальные документы – http://php.net/manual/en/function.flock.php