Question

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?

Was it helpful?

Solution

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.

OTHER TIPS

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 :)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top