Brad
Brad

Reputation: 950

PHP flock not having any effect in ubuntu

I have one php process locking a file with flock. I then start another process that deletes the file.

On windows, I get the correct behaviour where the locked file is not able to be deleted, however on ubuntu (both wsl and a full Ubuntu installation) I am always able to delete the file.

I have read other similar questions but they all seem to tested wrong. I am pretty sure I am testing this correctly.

UPDATED: More thorough testing. After reading Why is unlink successful on an open file? and the delete Queue in the file system I needed to also test read and write.

Testing method.

  1. Open a terminal and run my test file:

php test/flock_file_locking_with_splfileobject.php 👈 locks the file and waits for 30 seconds

  1. Open a second terminal and run the following:
php test/flock_file_locking_with_splfileobject.php read
php test/flock_file_locking_with_splfileobject.php write
php test/flock_file_locking_with_splfileobject.php delete

Here's the contents of test/flock_file_locking_with_splfileobject.php

See comments in the code describing the output I get.

<?php
$me = array_shift($argv);

$command = array_shift($argv);

$fileName = 'cats';

switch ($command) {
    case 'delete':
        //attempt to delete the file
        if (!unlink($fileName)) {
            echo "Failed to delete file!";
            exit(1);
        }
        echo "File was deleted:";
        var_dump(file_exists($fileName) === false);
        //on linux I get File was deleted:bool(true)
        //on windows I get 'PHP Warning:  unlink(cats): Resource temporarily unavailable'
        break;
    case 'write':
        $written = file_put_contents($fileName, 'some datah!');
        echo "Written bytes:";
        var_dump($written);
        //on Linux I get 'Read: string(21) "file should be locked"'
        // OR 'Read: string(11) "some datah!"' if I run the write command first.
        //on windows i get Warning: file_put_contents(): Only 0 of 11 bytes written, possibly out of free disk space
        break;
    case 'read':
        $read = file_get_contents($fileName);
        echo "Read: ";
        var_dump($read);
        // on Linux i get 'Written bytes:int(11)'
        // on windows I get no error but I get no data 'Read: string(0) ""'
        break;
    default:
        $file = new \SplFileObject($fileName, 'a+');//file gets created by a+
        if (! $file->flock(LOCK_EX)) {
            echo "Unable to lock the file.\n";
            exit(1);
        }
        $file->fwrite('file should be locked');
        echo "File should now be locked, try running the delete/write/read commands in another terminal.",
            "I'll wait 30 seconds and try to write to the file...\n";
        sleep(30);
        if (! $file->fwrite('file is now unlocked')) {
            echo "Unable to write to file.\n";
            exit(1);
        }
        //in either system this file write succeeds regardless of whats going on.
        break;
}
echo "\n";

Windows behaves as it should but on Linux, my 2nd process can do anything it likes to the file while the first process apparently gets a successful file lock.

Obviously, can't trust flock on production if it only works on windows. Is there any way to actually get an exclusive file lock?

Any ideas?

Upvotes: 0

Views: 181

Answers (0)

Related Questions