Does php's file_get_contents ignore file locking?
Asked Answered
C

2

7

I have read php's manual page on the 'file_get_contents' function which does not state anything about how 'file_get_contents` behaves with respect to php's file locking. However in the comment section user Chris suggests that

file_get_contents does not normally respect PHP's flock locking, i.e. advisory locking.

You can workaround this with some extra code to request a shared lock, like...

<?php
$tmp = fopen($path, 'rb');
@flock($tmp, LOCK_SH);
$contents = file_get_contents($path);
@flock($tmp, LOCK_UN);
fclose($tmp);
?>

which I have tested with success. I have also tested that even though a file has been locked with flock() exclusively LOCK_EX it was possible to have another php process read the file via file_get_contents as the comment would have suggested.

However, and that is mainly why I ask for information, I have read a webpage titled "Reading locked files in PHP", which claimed the following with regards to file_get_contents and file locking.

Reading a locked file with file_get_contents()

This is one the worst way to read a file while it is locked and modified, because:
- file_get_contents() will return an empty string (like in "")
- filesize() will return the actual number of bytes written to the file

I this claim correct? I run some tests, locking a file exclusively and constantly writing to it, while using file_get_contents in another php process to read the file and have not experienced the behaviour that as stated above

file_get_contents() will return an empty string (like in "")

Is it true in general that, php's file_get_contents does not care anything about the advisory file locking. Also, am I assuming correctly that the claims made in the webpage of the empty string returned by file_get_contents is empty "", is only true if the file is empty, or temporarily empty (while being modified) but not generally empty (only for the reason of the file being flock()ed)?

Crash answered 13/3, 2018 at 18:5 Comment(0)
S
4

flock is relatively independent of the file operations, you can even use fopen on a locked file. You as developer are responsible for checking/using flock everywhere you require a lock.

But yes in that regard it's true that file_get_contents has no build-in way to acquire a read lock when reading the file. So the workaround would be the way to go.

file_put_contents allows you to get a lock for writing though.

Suckle answered 13/3, 2018 at 18:18 Comment(3)
If I understand your answer correctly, There is nothing to assume that file_get_contents would henceforth return necessarily an empty "", because of a file lock. Without a file lock the data read via file_get_contents might not be reliable maybe (as no concurrent editions might occur) but I should not assume that file_get_contents would kind of check a file lock implicitly and return an empty string? (as was indicated in the second resource linked in the question), correct?Crash
Correct, it may be that the locking results in some strange side effect, but I doubt that.Suckle
I'm just getting to grips with locking myself, (so I cannot claim to be an "expert") but from what I understand, when a file is written out, the file size is set to zero, and pointer set to start of file before the data is written out. If a file_get_content reads the file at the =EXACT= millisecond the other file is writing out (since it ignores the lock) it will see the empty file.Glossography
G
0

flock in shared mode will allow read access to the file. flock in exclusive mode will allow read/write access. A shared or exclusive lock will cause the next thread to set an exclusive lock to wait until the lock is released. While waiting a following file_get_contents will not be excuted until the lock is released by the thread that set the lock. Multiple threads may set a shared lock and continue with read access. The file_get_contents will be executed without wait (unless there is an exclusive lock active.)

Consider a situation where you want to protect a section of code that only one thread at a time may execute. You set an exclusive lock on any file, that may never be written to and only exists as a lock sentinal. After the section of code you unlock and allow the next thread to continue. Beware, the protected section must be short to prevent delays and queue's. Also if you use multiple locks they shoud be used in a common order to prevent deadlocks.

Galoot answered 5/9 at 9:1 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.