note 47028 added to function.flock

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

« previous php.notes (#79389) next »