[-] 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:
+7
-21
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user