0

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?

Brad
  • 741
  • 7
  • 17
  • 1
    Perhaps https://stackoverflow.com/questions/23287997/why-is-unlink-successful-on-an-open-file gives some ideas. Sounds like the `unlink` only marks it for deletion on linux. – Nigel Ren Apr 12 '21 at 07:57
  • Thanks, that does give some insight and perhaps I need to be testing more than just delete scenario to see if it's the underlying filesystem. – Brad Apr 14 '21 at 04:00
  • 1
    As per the [docs](https://www.php.net/manual/en/function.flock.php#refsect1-function.flock-notes) only the Windows implementation is mandatory, the others are advisory. My reading of this is that any other accesses of the lock would need to call `flock` to check whether it has been locked via this mechanism; bypassing this with `unlink`, `file_put_contents` etc would just ignore it. – msbit Apr 16 '21 at 01:56

0 Answers0