[-] Fixes a race condition

Fixes a race condition leading to file coruption and PHP crashes when
writing the cache index file.

Handles concurrency properly by using a temporary file and an atomic
rename() instead of file_put_contents(), which is not atomic, on a
file which is potentially accessed by many processes at the same time
This commit is contained in:
Sébastien Bocahu
2013-04-26 14:28:01 +02:00
parent ea6b4eaef8
commit 2ac6e52c9f
+7 -21
View File
@@ -136,27 +136,13 @@ class Autoload
}
else
{
// Let's write index content in cache file
// In order to be sure that this file is correctly written, a check is done on the file content
$loop_protection = 0;
do
{
$integrity_is_ok = false;
file_put_contents($filename, $content, LOCK_EX);
if ($loop_protection++ > 10)
break;
// If the file content end with PHP tag, integrity of the file is ok
if (preg_match('#\?>\s*$#', file_get_contents($filename)))
$integrity_is_ok = true;
}
while (!$integrity_is_ok);
if (!$integrity_is_ok)
{
file_put_contents($filename, '<?php return array(); ?>', LOCK_EX);
// Cannot use PrestaShopException in this context
die('Your file '.$filename.' is corrupted. Please remove this file, a new one will be regenerated automatically');
$filename_tmp = tempnam(dirname($filename), basename($filename.'.'));
if($filename_tmp !== FALSE and file_put_contents($filename_tmp, $content, LOCK_EX) !== FALSE) {
rename($filename_tmp, $filename);
} else {
// $filename_tmp couldn't be written. $filename should be there anyway (even if outdated),
// no need to die.
error_log('Cannot write temporary file '.$filename_tmp);
}
}