Bug #51933 [NEW]: file_put_contents(...,FILE_APPEND|LOCK_EX) wrongly documented
| From: | dxjones at gmail dot com | Date: | Thu, 27 May 2010 17:09:22 +0000 |
| Subject: | Bug #51933 [NEW]: file_put_contents(...,FILE_APPEND|LOCK_EX) wrongly documented | ||
| Groups: | php.doc.bugs | ||
| Request: | Send a blank email to doc-bugs+get-4460@lists.php.net to get a copy of this message | ||
From:
Operating system: ALL
PHP version: Irrelevant
Package: Documentation problem
Bug Type: Bug
Bug description:file_put_contents(...,FILE_APPEND|LOCK_EX) wrongly documented
Description:
------------
This is a bug in the PHP documentation.
I verified the bug using PHP 5.2.10, but the problem is not in the code; it
is in the description.
The doc INCORRECTLY states that FILE_APPEND and LOCK_EX are "mutually
exclusive". This is just plain false. It also says something wonky about
appends being atomic.
Here is what I did to demonstrate the error.
1. I create a script "race.php" that appends to a file "race.csv"
2. The key line is:
file_put_contents('race.csv', $s, FILE_APPEND);
3. I use a tool "Jakarta" to generate a large amount of traffic (5000
fetches in just a few seconds).
3. When I look at the output file, there are fewer than 5000 lines.
4. I repeat the same experiment with a flag to use this key line:
file_put_contents('race-lock.csv', $s, FILE_APPEND|LOCK_EX);
5. The output file has exactly 5000 lines.
This proves there is an error in the documentation.
Goodness knows how much damage this error has caused.
For me, there were corrupted log files in several large online
applications.
The error only manifests when there is heavy traffic and multiple PHP
processes trying to append to the same file at the same time.
The documentation falsely instructs developers *NOT* to use
"FILE_APPEND|LOCK_EX".
There was even a correct code example in late 2009 that included
"FILE_APPEND|LOCK_EX". Rather than fix the documentation, they CHANGED THE
EXAMPLE (!) to remove "LOCK_EX". Sigh.
Please fix this.
Test script:
---------------
<? // race.php
// you will only see the error if you hit this script many times in a brief
period
// so there are multiple PHP processes trying to append to the same file at
the same time
// The PHP documentation FALSELY says you can't combine
"FILE_APPEND|LOCK_EX"
// Call this script 5000 times within just a few seconds, see if you get
5000 lines of output -- without LOCK_EX, you will LOSE DATA!!
$t = microtime(TRUE);
$alpha = array('A', 'B', 'C', 'D', 'E',
'F', 'G', 'H', 'I', 'J');
$r = rand(0,9);
$w = '';
for ($i = 0 ; $i < 20 ; ++$i) {
$w .= $alpha[$r];
}
$row = array( $alpha[$r] );
$row[]= sprintf('%.9f', $t);
for ($i = 0 ; $i < 64 ; ++$i) {
$row[] = $w . sprintf('%02d',$i);
}
$row[] = $alpha[$r];
$row[] = sprintf('%.9f', microtime(TRUE) - $t);
$s = implode(',',$row) . "\n";
if (array_key_exists('reset', $_REQUEST)) {
system('rm -f race.csv race-lock.csv');
} elseif (array_key_exists('lock', $_REQUEST)) {
file_put_contents('race-lock.csv', $s, FILE_APPEND | LOCK_EX);
} else {
file_put_contents('race.csv', $s, FILE_APPEND);
}
?>
<html><head><title>race</title></head><body><h1>race</h1></body></html>
Expected result:
----------------
look inside the output files:
race.csv -- expect to have exactly 5000 lines, but might have fewer than
5000 lines because of error in documentation
race-lock.csv -- will have exactly 5000 lines because FILE_APPEND|LOCK_EX
is used
Actual result:
--------------
race.csv -- has fewer than 5000 lines because of error
--
Edit bug report at http://bugs.php.net/bug.php?id=51933&edit=1
--
Try a snapshot (PHP 5.2): http://bugs.php.net/fix.php?id=51933&r=trysnapshot52
Try a snapshot (PHP 5.3): http://bugs.php.net/fix.php?id=51933&r=trysnapshot53
Try a snapshot (trunk): http://bugs.php.net/fix.php?id=51933&r=trysnapshottrunk
Fixed in SVN: http://bugs.php.net/fix.php?id=51933&r=fixed
Fixed in SVN and need be documented: http://bugs.php.net/fix.php?id=51933&r=needdocs
Fixed in release: http://bugs.php.net/fix.php?id=51933&r=alreadyfixed
Need backtrace: http://bugs.php.net/fix.php?id=51933&r=needtrace
Need Reproduce Script: http://bugs.php.net/fix.php?id=51933&r=needscript
Try newer version: http://bugs.php.net/fix.php?id=51933&r=oldversion
Not developer issue: http://bugs.php.net/fix.php?id=51933&r=support
Expected behavior: http://bugs.php.net/fix.php?id=51933&r=notwrong
Not enough info: http://bugs.php.net/fix.php?id=51933&r=notenoughinfo
Submitted twice: http://bugs.php.net/fix.php?id=51933&r=submittedtwice
register_globals: http://bugs.php.net/fix.php?id=51933&r=globals
PHP 4 support discontinued: http://bugs.php.net/fix.php?id=51933&r=php4
Daylight Savings: http://bugs.php.net/fix.php?id=51933&r=dst
IIS Stability: http://bugs.php.net/fix.php?id=51933&r=isapi
Install GNU Sed: http://bugs.php.net/fix.php?id=51933&r=gnused
Floating point limitations: http://bugs.php.net/fix.php?id=51933&r=float
No Zend Extensions: http://bugs.php.net/fix.php?id=51933&r=nozend
MySQL Configuration Error: http://bugs.php.net/fix.php?id=51933&r=mysqlcfg