note 47028 added to function.flock
| From: | pentek_imre at mailbox dot hu | Date: | Sun, 31 Oct 2004 11:51:54 +0000 |
| Subject: | note 47028 added to function.flock | ||
| Groups: | php.notes | ||
| Request: | Send a blank email to php-notes+get-79389@lists.php.net to get a copy of this message | ||
flock isn't good in race conditions. I accept that it can correctly lock file and can correctly
block php processes if file is locked, but anyway this function isn't the right way to manage a
race condition.
Let's have a look at this code:
<?php
$f=fopen($filename,"a+") or die();
flock($f,LOCK_EX) or die();
//here write some lines to the file -- not included
//then close:
flock($f,LOCK_UN) or die();
fclose($f) or die();
?>
Then generate a race situation with two php processes:
1: open file ok, no file found, create
2: open file ok, file found seek to the end (0lenght file so to the beginning)
1: lock file ok
2: flock waits since file is already locked.
1: write ok
1: unlock ok
2: flock ok this process now continues
1: fclose ok
2: write something, but due to prebuffering the file is now empty, so content written by 1 is now
unconsidered, forgotten.
2: unlock ok
2: fclose ok
file will have only the content from process 2
this is the situation if you use r+ too, no matter if you used fflush or not.
conclusion: you may want to create a separate lock file!
separate lock file will behave like in the previous example too, so let's try LOCK_NB and
$wouldblock, file close and reopen.
let's see this example:
<?php
$file="/tmp/phplockfile";
do
{
if(isset($f))
{
flock($f,LOCK_UN);
fclose($f);
}
$f=fopen($file,"a") or die();
flock($f,LOCK_EX+LOCK_NB,$W);
// sleep(1);
}
while ($W==1);
//lock is mine:
echo $_SERVER["UNIQUE_ID"]." ".date("r")."\n";
sleep(1);
echo $_SERVER["UNIQUE_ID"]." ".date("r")."\n";
//release the lock:
flock($f,LOCK_UN);
fclose($f);
?>
I tried this code for 10 (ten) parellel processes. only three of them succeeds to lock the file and
unlock it, the other seven quits with execuition timeout. uncommenting the sleep(1); won't help
too, just execution will be longer (30 sec is counted not as real time but as cpu time)
I tried random usleep too, as I remember this wasn't helped too.
Remember that file close and reopen is a must becouse processes may write to the file, and this way
these extra bytes will be considered too.
----
Manual Page -- http://www.php.net/manual/en/function.flock.php
Edit -- http://master.php.net/manage/user-notes.php?action=edit+47028
Delete -- http://master.php.net/manage/user-notes.php?action=delete+47028&report=yes
Reason: bad code -- http://master.php.net/manage/user-notes.php?action=delete+47028&report=yes&reason=bad+code
Reason: spam -- http://master.php.net/manage/user-notes.php?action=delete+47028&report=yes&reason=spam
Reason: useless example -- http://master.php.net/manage/user-notes.php?action=delete+47028&report=yes&reason=useless+example
Reason: contains commercial links -- http://master.php.net/manage/user-notes.php?action=delete+47028&report=yes&reason=contains+commercial+links
Reason: useless note -- http://master.php.net/manage/user-notes.php?action=delete+47028&report=yes&reason=useless+note
Reject -- http://master.php.net/manage/user-notes.php?action=reject+47028&report=yes
Search -- http://master.php.net/manage/user-notes.php