PHP-файл скрипта загружается в браузер бесконечно долго (LOCK_SH / LOCK_EX) - PullRequest
0 голосов
/ 15 ноября 2018

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

Я создал два сценария, readandwritelock.php и readlock.php, первый сценарий для извлечения файла с помощью file_get_contents, добавьте его, а затем запишите обратно в тот же файл с помощью file_put_contents($file, $data, LOCK_EX), а второй, который просто извлекает файл с помощьюfile_get_contents после flock($file, LOCK_SH).

<?php
    //readandwritelock.php

    $myfile = fopen('15-11-2018.txt', 'r+');
    if (flock($myfile, LOCK_SH)) {

        echo "Gotten lock<br>";
        $current = file_get_contents('15-11-2018.txt');

        /*I commented this on my second test to see if file_put_contents will work.
        After uncommenting and third test, it does not work anymore.

        if (flock($myfile, LOCK_UN)) {

            echo "Unlocked<br>";
        }*/

        $current .= "appending";

        if (file_put_contents('15-11-2018.txt', $current, LOCK_EX)) {
            echo "Success";
        }
        else {
            echo "Failed";
            //browser loads indefinitely so this does not run
        }

        fclose($myfile);
    }
?>

Проблема, с которой я сталкиваюсь, заключается в том, что с первой попытки я смог file_get_contents получить блокировку, а затем снять блокировку и перейти к добавлению и file_put_contents($file, $data, LOCK_EX).Однако со второй попытки я решил прокомментировать выпуск блокировки LOCK_SH, чтобы проверить и посмотреть, что произойдет.Файл сценария загружается бесконечно (в ожидании localhost ...) в моем браузере, поэтому я вернул изменения для третьей попытки, но на этот раз файл сценария по-прежнему загружается неопределенно долго.Как будто LOCK_SH так и не был выпущен.

Я, должно быть, что-то делаю не так, но я не знаю, что именно.Может кто-нибудь объяснить?

Это было проверено на XAMPP и macOS High Sierra и Chrome.

<?php
    //readlock.php
    //works as normal
    $myfile = fopen('15-11-2018.txt', 'r');

    if (flock($myfile, LOCK_SH)) {

        echo "Gotten lock<br>";
        $current = file_get_contents('15-11-2018.txt');
        echo $current;

        if (flock($myfile, LOCK_UN)) {
            echo "<br>Unlocked";
        }
        fclose($myfile);
    }
?>

1 Ответ

0 голосов
/ 15 ноября 2018

Причина, по которой ваш браузер загружается бесконечно, заключается в том, что ваш PHP-файл никогда не заканчивается.

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

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

if( flock($myfile, LOCK_EX) ) {
    // ...

или вы разблокируете общую блокировку, прежде чем писать

flock($myfile, LOCK_UN);
if ( file_put_contents('15-11-2018.txt', $current, LOCK_EX) ) {
    // ...

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

...