I see people using flock like this:
if (!$fp = fopen($file_name, 'wb'))
{
return FALSE;
}
if (flock($fp, LOCK_EX))
{
fwrite($fp, serialize($data));
flock($fp, LOCK_UN);
}
Also this:
if (!$fp = @fopen($file_name, 'rb'))
{
return FALSE;
}
flock($fp, LOCK_SH);
$data = '';
if (filesize($file_name) > 0)
{
$data = unserialize(fread($fp, filesize($file_name)));
}
But isn't there a chance that someone else will edit the file between the fopen
call and the flock
call? and the same question for fread
EDIT:
To clarify why I'm asking this... I'm basing my question on the code here, In a mysql caching situation, what's to stop 20 people from all being able to access the file at the same time if they all can get in between the fopen and flock?
Is that code foolproof?
You ask:
isn't there a chance that someone else will edit the file between the fopen call and the flock call? and the same question for fread
Yes, no, maybe. Short answer: assume "yes" and act carefully.
Yes, in that traditional flock()-based locking is merely advisory, so other processes (or even the same process) are free to disregard the locks. In practice, this is not a problem, as flock() is used by well-behaved client code — you don't read until you get a LOCK_SH, and you don't write unless you've obtained a LOCK_EX — on application-specific files.
No, in that PHP's implementation of flock() may be mandatory on certain operating systems, per the documentation, which might also require support from the filesystem (e.g., as with the mand option under Linux). So, other processes could not disregard those locks.
Maybe, in that the streams subsystem in PHP 5 implements some locking bookkeeping beyond that provided by the operating system. This may, for example, prevent the same process (but not another) from disregarding its own otherwise advisory locks. The behavior might surprise some. Even so, this kind of locking would not be mandatory between unrelated processes.
For portability, just assume the weakest semantics (the "yes" above) and restrict flock()ing to well-behaved code on application-specific lockfiles chosen in advance.
First snippet is fool-proof, if you can't get a lock on the file, you don't write. If someone else edited the file between fopen()
and flock()
, your file handle will point to the latest incarnation, since fopen()
binds to a stream, rather than to a 'snapshot'.
Second example is not guaranteed to work, because the return value of flock()
is not checked, so if you haven't acquired the lock, the subsequent code will be executed anyway.
[edit] removed statement that reader lock doesn't matter, it actually does, as explained in comments below :)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With