phptal / PHPTAL

PHP Template Attribute Language — template engine for XSS-proof well-formed XHTML and HTML5 pages
http://phptal.org
GNU Lesser General Public License v2.1
178 stars 42 forks source link

Need atomic write when preparing code #61

Open alantum opened 6 years ago

alantum commented 6 years ago

in line PHPTAL.php:828 used not atomic writes via file_put_contents if (!file_put_contents($this->getCodePath(), $result)) {

OpCache in some cases is in time to store an empty file into the cache. Potential reasons for it is high RPS, high concurency, slow disks and so on.

File exists, it's not empty, there are no errors while requiring file, but function is not defined and we have this log message: E_ERROR: Call to undefined function tpl_... in: /var/local/www/app/outsource/PHPTAL/PHPTAL.php:667

Ocramius commented 6 years ago

Would adding a LOCK_EX solve this?

alantum commented 6 years ago

http://php.net/manual/en/apc.configuration.php#ini.apc.file-update-protection

When a file is modified on a live web server it really ought to be done in an atomic manner. That is, written to a temporary file and renamed (mv) the file into its permanent position when it is ready.

Ocramius commented 6 years ago

apc is really really really really really really to be avoided. It is unstable, unmaintained and can lead to random segfaults due to internal memory corruption. If the file has to be written atomically, an exclusive lock may work (although it may lead to some errors while multiple client re-generate the cache: dogpiling-alike)

alantum commented 6 years ago

I took APC as good documented example. In real project we use OpCache https://secure.php.net/manual/en/opcache.configuration.php#ini.opcache.file_update_protection

shivashanti commented 5 years ago

I think it will improve even with LOCK_EX, Probably not enough for LOCK_EX.  The code generating process needs to create a temporary file and mv it. Because there is a very very short time from file open to lock. If other process read the file at that time, it will appear as an empty.