-
Notifications
You must be signed in to change notification settings - Fork 7.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Opcache corruption #8846
Comments
Well, the problem is that on the first request, the I think we should treat this as WONTFIX, since fixing this issue (and related issues) would make OPcache less efficient, and it seems to be a uncommon edge-case anyway. |
It's very easy to reproduce with activating 2 different versions of a simple WordPress plugin twice, then realizing your error and deactivating one of the plugins. |
It is a bug, opcache should work /wo any side effect. Class can be loaded from cache only if the containing file was required/included in the current request/preload. |
One may argue that the user should cater to such changes by calling |
It doesn't seem like this is how Opcache is supposed to work. If it were acceptable, which I don't think it is, that Opcache should be corrupted by certain user actions or have unexpected behavior, this should probably be well documented in a public visible document (e.g. https://www.php.net/opcache ) and all those cases described. I don't think it's reasonable to expect a regular user or a developer or even a sys admin to be able to quickly see, diagnose and solve such a problem. Neither is calling |
Hi @vnsavage, |
Hey @IAMBANN my tests show that it's still reproducible under PHP 8.1. Did you follow all the steps I listed, creating the exact same files and issuing 2 requests while modifying test.php between the 2 requests? Were you able to reproduce it with the earlier versions? Do you have opcache enabled? |
Hey @IAMBANN
The instructions call for 2 web requests to be issued, not one. The unexpected output appears only on the 2nd web request, and after the file modification, as that's the one using Opcache. In order to try and stop this from going in circles, here is a list of commands you can run with a Docker image to reproduce it:
|
For context: https://www.npopov.com/2021/10/20/Early-binding-in-PHP.html I had a look. This is what happens:
On the second execution, only step 4 is executed. Usually this would work fine due to early binding, but since when the script was compiled the class was already declared no early binding is attempted. Opcache actually already solves this problem with delayed early binding. When loading a script from opcache, all delayed early bindings are attempted again. However, for some reason delayed early binding is only implemented for classes with parent classes. I implemented added support for classes without parents here: #11227 This still has some subtle issues. In particular, the scripts are still order-dependent. That means if we compile files in one way, but then include them in another, we might get or not get delayed early binding. I think it would be better to consistently always delayed early bind classes when opcache is enabled, but I believe this would not be BC compatible, because with early binding, delayed early binding and then runtime definition we get a "3 level implicit topological sort" (meaning we can create three levels of inheritance in the same file in any order). Moving early binding to delayed early binding would remove one level. To be fair, this would already break without opcache, as we only have two levels with early binding and runtime definition. |
Description
The following code:
Resulted in this output:
But I expected this output instead:
PHP Version
PHP 8.0
Operating System
Linux
The text was updated successfully, but these errors were encountered: