News:

Wondering if this will always be free?  See why free is better.

Main Menu

Site suddenly not working

Started by SethStudent, December 11, 2019, 10:50:56 AM

Previous topic - Next topic

Shambles

I checked out the GH conversation on this fault but didn't see a resolve, unless it's in the pipeline there?

Anyway, I looked at the cache_put_data function declared in Load.php and can see this block of code:

Code (Load.php::cache_put_data) Select
<?php
$fh = @fopen($cachedir '/data_' $key '.php''w');
if ($fh)
{
// Write the file.
set_file_buffer($fh0);
flock($fhLOCK_EX);
$cache_bytes fwrite($fh$cache_data);
flock($fhLOCK_UN);
fclose($fh);

// Check that the cache write was successful; all the data should be written
// If it fails due to low diskspace, remove the cache file
if ($cache_bytes != strlen($cache_data))
@unlink($cachedir '/data_' $key '.php');
}


The attempt to secure an exclusive write lock (flock($fh, LOCK_EX)) isn't tested for success before the fwrite is performed, and in a non-locked scenario could the fwrite be returning the number of bytes it was asked to write as opposed to the number it actually wrote, thereby avoiding the ensuing length check and leading to an incomplete/corrupt cached copy of the modSettings file?


live627

No resolution that I know of. The only proposed change related to this is proposing a filesystem lock.

You're right that the result of the lock should be checked, but fwrite will work fine without a lock.

That code block that you've isolated is a fallback for if file_put_contents is missing, a rarity nowadays.

All writing does use locks. Good. Now the reading must also use locks. Observe my code:

<?php

private function 
readFile($file)
{
if (($fp fopen($file'rb')) !== false)
{
if (!flock($fpLOCK_SH LOCK_NB))
{
fclose($fp);
return false;
}
$string '';
while (!feof($fp))
$string .= fread($fp8192);

flock($fpLOCK_UN);
fclose($fp);

return $string;
}

return false;
}

private function writeFile($file$string)
{
if (($fp fopen($file'cb')) !== false)
{
if (!flock($fpLOCK_EX LOCK_NB))
{
fclose($fp);
return false;
}
ftruncate($fp0);
$bytes 0;
$pieces str_split($string8192);
foreach ($pieces as $piece)
{
if (($val fwrite($fp$piece8192)) !== false)
$bytes += $val;
else
return false;
}
fflush($fp);
flock($fpLOCK_UN);
fclose($fp);

return $bytes;
}


The reader uses a shared  lock, meaning that no one else can acquire exclusive lock for writing. Any number of processes can acquire a shared lock.


The cache code in SMF does not bother with shared locks, and instead simply uses include(). 2.1 suppresses any parse errors which may result from partiality written files.



The common denominator in these bug reports that I could verify was a file size cutoff of KB.

shawnb61

Closing - This was addressed in 2.0.18.
Address the process rather than the outcome.  Then, the outcome becomes more likely.   - Fripp

wakewatcher

Quote from: shawnb61 on February 01, 2021, 05:49:07 PMClosing - This was addressed in 2.0.18.

Apparently not.  I'm running 2.0.18 and had this happened last night for the first time. Because this has such a significant effect (site won't run at all) I've disabled caching and emptied the cache. If anyone is interested I can upload the file.  Don't see that I can do it here.
smf 2.0.18

Advertisement: