php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #65559 Opcache: cache not cleared if changes occur while running
Submitted: 2013-08-26 12:41 UTC Modified: 2013-11-25 10:41 UTC
Votes:9
Avg. Score:4.4 ± 0.8
Reproduced:8 of 8 (100.0%)
Same Version:6 (75.0%)
Same OS:5 (62.5%)
From: zoeslam at gmail dot com Assigned: dmitry
Status: Closed Package: opcache
PHP Version: 5.5.3 OS: Ubuntu
Private report: No CVE-ID:
 [2013-08-26 12:41 UTC] zoeslam at gmail dot com
Description:
------------
The new Zend OPcache doesn't clear the cache if a file is changed on the fly.

Instead the test script works well with opcache turned off (opcache.enable=0).

Test script:
---------------
<?php
$file = __DIR__.'/file.txt';
file_put_contents($file, '<?php return 1;');
$var = include $file;
file_put_contents($file, '<?php return 2;');
$var = include $file;
var_dump($var);

Expected result:
----------------
int(2)

Actual result:
--------------
int(1)

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2013-10-23 14:09 UTC] zoeslam at gmail dot com
Of course, if you try the test in CLI, make sure to enable the opcache even in the cli:

php -d opcache.enable=1 -d opcache.enable_cli=1 test.php
 [2013-11-04 14:48 UTC] arjen at react dot com
Don't think this is a bug. opcache_invalidate()/opcache_reset() isn't called after the updated file is written to disk, so the opcache just doesn't know the file on disk has changed. The timestamps are only validated every 2 sec. by default, but only once per request.

See http://www.php.net/manual/en/opcache.configuration.php#ini.opcache.revalidate-freq and Speed Tuning @ https://github.com/zendtech/ZendOptimizerPlus
 [2013-11-04 14:54 UTC] zoeslam at gmail dot com
Maybe you are right, but this is a huge inconsistency, difference and compatibility break from APC, which was the default opcache in 5.4.

(Just tested with Opcache disabled and php -d extension=apc.so -d apc.enabled=1 -d apc.enable_cli=1 test.php)
 [2013-11-05 06:50 UTC] dmitry@php.net
-Status: Open +Status: Assigned -Assigned To: +Assigned To: dmitry
 [2013-11-19 13:46 UTC] Terry at ellisons dot org dot uk
Why is this a problem? This is the analog of apc.stat.  The only material difference here is that apc.stat=1 by default.  OPcache defaults are different, but this is clearly documented.  If you want OPcache always to revalidate scripts, then set opcache.revalidate_freq=0 as per README and documentation.
 [2013-11-19 13:52 UTC] zoeslam at gmail dot com
Well, just tested with

php -d opcache.enable=1 -d opcache.enable_cli=1 -d opcache.revalidate_freq=0 test.php

and the result is the same, int(1), so the issue is still alive.
 [2013-11-19 14:04 UTC] arjen at react dot com
-d opcache.revalidate_freq=0  will result in OPcache checking for updates on every request.

You change the content DURING the request, so OPcache won't check for updates during the request.

http://www.php.net/manual/en/apc.configuration.php#ini.apc.stat
"This defaults to on, forcing APC to stat (check) the script on each request to determine if it has been modified."

Reads the same as opcache.revalidate. Because of your bugreport I guess apc.stat=1 checks the file on disk for modification on every include/require. And not just once per request, which is quite different..
 [2013-11-21 22:01 UTC] nanobreaker at mail dot bg
I have the same problem. If I change a file nothing happens. For development purposes I tried to disable OPCache, but that doesn't work as well. Only way I can fix this problem is by rebooting the system.

Details:
 Ubuntu Server 13.10 x64
 PHP 5.5.3
 Apache 2.4.6
 [2013-11-25 10:41 UTC] dmitry@php.net
APC made a hack to prevent caching of just updated files.
This makes the test passed.

With opcache.revalidate_freq=0 OPCache checks file modification time on each include(), but the test script most probably makes two writes in a single second.
So file modification times are the same. If you insert sleep(1) between inclue()s, it works as expected.

To workaround the problem you may add the file into blacklist or use opcache_invalidate():

if (function_exists("opcache_invalidate")) opcache_invalidate($file, true);

We may also hack OPCache similar to APC, but I'm not sure it's the right way.
 [2013-11-25 10:54 UTC] zoeslam at gmail dot com
Hi dmitry, almost all http requests last less than 1 second, and it's common to write this cache algorithm:

$var = include $cachefile;
if (must_renew($var)) {
    file_put_contents($cachefile, renew($var));
    $var = include $cachefile;
}
use($var);

So I think APC did a workaround just because of that common usage.
Your workaround works, but it' pretty bad to couple a general algorithm to teh cache subsystem.
 [2013-11-26 07:37 UTC] dmitry@php.net
Automatic comment on behalf of dmitry@zend.com
Revision: http://git.php.net/?p=php-src.git;a=commit;h=a8c7e50f4d7d73797615734978259d640b3835c1
Log: Fixed bug #65559 (Opcache: cache not cleared if changes occur while running)
 [2013-11-26 07:37 UTC] dmitry@php.net
-Status: Assigned +Status: Closed
 [2013-11-26 10:00 UTC] ab@php.net
Automatic comment on behalf of dmitry@zend.com
Revision: http://git.php.net/?p=php-src.git;a=commit;h=a8c7e50f4d7d73797615734978259d640b3835c1
Log: Fixed bug #65559 (Opcache: cache not cleared if changes occur while running)
 [2014-03-26 01:20 UTC] roger dot qiu at polycademy dot com
This is still a problem, because include is sometimes used for non-source code files that can be changed under 1 second during runtime.

https://github.com/tedivm/Stash/pull/135#issuecomment-38640785
 
PHP Copyright © 2001-2014 The PHP Group
All rights reserved.
Last updated: Wed Apr 23 18:01:55 2014 UTC