note 32443 modified in function.flock by danbrown

From: Date: Mon, 18 May 2009 00:48:53 +0000
Subject: note 32443 modified in function.flock by danbrown
References: 1  Groups: php.notes 
Request: Send a blank email to php-notes+get-155435@lists.php.net to get a copy of this message
I have found that if you open a currently locked file with 'w' or 'w+' ("file pointer at the beginning of the file and truncate the file to zero length") then it will not truncate the file when the lock is released and the file available. Example I used to test it: <?php // a.php $fp = fopen( "/tmp/lock.txt", "w+" ); flock( $fp, LOCK_EX ); // exclusive lock $steps = 10; // write to the file for ($i=0; $i< $steps; $i++) { fwrite($fp, 'a '.time().' test '. $i."\n"); sleep(1); } flock( $fp, LOCK_UN ); // release the lock fclose( $fp ); ?> ---------- <?php // b.php $fp = fopen( "/tmp/lock.txt", "w+" ); flock( $fp, LOCK_EX ); // exclusive lock // ftruncate($fp, 0) is needed here! <---- $steps = 5; // write to the file for ($i=0; $i< $steps; $i++) { fwrite($fp, 'b '.time().' test '. $i."\n"); sleep(1); } flock( $fp, LOCK_UN ); // release the lock fclose( $fp ); ?> Loading a.php then loading b.php right after will result in: b 1054075769 test 0 b 1054075770 test 1 b 1054075771 test 2 b 1054075772 test 3 b 1054075773 test 4 a 1054075764 test 5 a 1054075765 test 6 a 1054075766 test 7 a 1054075767 test 8 a 1054075768 test 9 As you can see, b.php does not truncate the file as the w+ would suggest if the file were instantly available. But only moves the pointer to the begining of the file. If b.php was loaded after a.php finished then there would be no "a ..." lines in the file, since it would be truncated. To fix this you have to add ftruncate($fp, 0) right after the flock. 'r+' and 'a' seem to work fine, though. --was-- I have found that if you open a currently locked file with 'w' or 'w+' ("file pointer at the beginning of the file and truncate the file to zero length") then it will not truncate the file when the lock is released and the file available. Example I used to test it: a.php: $fp = fopen( "/tmp/lock.txt", "w+" ); flock( $fp, LOCK_EX ); // exclusive lock $steps = 10; // write to the file for ($i=0; $i< $steps; $i++) { fwrite($fp, 'a '.time().' test '. $i."\n"); sleep(1); } flock( $fp, LOCK_UN ); // release the lock fclose( $fp ); ---------- b.php: $fp = fopen( "/tmp/lock.txt", "w+" ); flock( $fp, LOCK_EX ); // exclusive lock // ftruncate($fp, 0) is needed here! <---- $steps = 5; // write to the file for ($i=0; $i< $steps; $i++) { fwrite($fp, 'b '.time().' test '. $i."\n"); sleep(1); } flock( $fp, LOCK_UN ); // release the lock fclose( $fp ); Loading a.php then loading b.php right after will result in: b 1054075769 test 0 b 1054075770 test 1 b 1054075771 test 2 b 1054075772 test 3 b 1054075773 test 4 a 1054075764 test 5 a 1054075765 test 6 a 1054075766 test 7 a 1054075767 test 8 a 1054075768 test 9 As you can see, b.php does not truncate the file as the w+ would suggest if the file were instantly available. But only moves the pointer to the begining of the file. If b.php was loaded after a.php finished then there would be no "a ..." lines in the file, since it would be truncated. To fix this you have to add ftruncate($fp, 0) right after the flock. 'r+' and 'a' seem to work fine, though. http://php.net/manual/en/function.flock.php

« previous php.notes (#155435) next »