Skip to content

Opcache breaks autoloading after E_COMPILE_ERROR #8063

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

Closed
shira-374 opened this issue Feb 8, 2022 · 3 comments
Closed

Opcache breaks autoloading after E_COMPILE_ERROR #8063

shira-374 opened this issue Feb 8, 2022 · 3 comments

Comments

@shira-374
Copy link

shira-374 commented Feb 8, 2022

Description

If an E_COMPILE_ERROR is raised during autoloading with opcache enabled, it breaks autoloading during the shutdown process in subsequent requests.

Multiple files are required to reproduce this, so I've put them in this gist:
https://gist.github.com/shira-374/d2077e5581ce5ec53c655c7373846147

With opcache enabled, the script works once, then it always fatals twice. Without opcache it always works as expected.

<?php

spl_autoload_register(function (string $name) {
    echo "Autoloading: {$name}<br>\n";
    require __DIR__ . '/' . $name . '.php';
});

register_shutdown_function(function () {
    new Bar(); // this triggers E_COMPILE_ERROR again for BadClass (???)
    new Baz();
    echo "Finished<br>\n";
});

new BadClass(); // this triggers E_COMPILE_ERROR

Resulted in this output:

Autoloading: BadClass
Autoloading: Foo

Fatal error: Declaration of BadClass::dummy() must be compatible with Foo::dummy(): void in /var/www/html/BadClass.php on line 5
Autoloading: Bar

Fatal error: Declaration of BadClass::dummy() must be compatible with Foo::dummy(): void in /var/www/html/BadClass.php on line 5

But I expected this output instead:

Autoloading: BadClass
Autoloading: Foo

Fatal error: Declaration of BadClass::dummy() must be compatible with Foo::dummy(): void in /var/www/html/BadClass.php on line 5
Autoloading: Bar
Autoloading: Baz
Finished

PHP Version

8.1.2

Operating System

Debian 11.2

@cmb69
Copy link
Member

cmb69 commented Feb 9, 2022

This looks like an unintended side-effect of dd86987.

arnaud-lb added a commit that referenced this issue Apr 3, 2022
Recorded errors may be attached to the wrong cached script when a fatal error
occurs during recording. This happens because the fatal error will cause a
bailout, which may prevent the recorded errors from being freed. If an other
script is compiled after bailout, or if a class is linked after bailout, the
recorded errors will be attached to it.

This change fixes this by freeing recorded errors before executing shutdown
functions.

Fixes GH-8063
arnaud-lb added a commit to arnaud-lb/php-src that referenced this issue Apr 3, 2022
Recorded errors may be attached to the wrong cached script when a fatal error
occurs during recording. This happens because the fatal error will cause a
bailout, which may prevent the recorded errors from being freed. If an other
script is compiled after bailout, or if a class is linked after bailout, the
recorded errors will be attached to it.

This change fixes this by freeing recorded errors before executing shutdown
functions.

Fixes phpGH-8063
arnaud-lb added a commit to arnaud-lb/php-src that referenced this issue Apr 15, 2022
Recorded errors may be attached to the wrong cached script when a fatal error
occurs during recording. This happens because the fatal error will cause a
bailout, which may prevent the recorded errors from being freed. If an other
script is compiled after bailout, or if a class is linked after bailout, the
recorded errors will be attached to it.

This change fixes this by freeing recorded errors before executing shutdown
functions.

Fixes phpGH-8063
arnaud-lb added a commit to arnaud-lb/php-src that referenced this issue Apr 22, 2022
Recorded errors may be attached to the wrong cached script when a fatal error
occurs during recording. This happens because the fatal error will cause a
bailout, which may prevent the recorded errors from being freed. If an other
script is compiled after bailout, or if a class is linked after bailout, the
recorded errors will be attached to it.

This change fixes this by freeing recorded errors before executing shutdown
functions.

Fixes phpGH-8063
arnaud-lb added a commit to arnaud-lb/php-src that referenced this issue Apr 22, 2022
Recorded errors may be attached to the wrong cached script when a fatal error
occurs during recording. This happens because the fatal error will cause a
bailout, which may prevent the recorded errors from being freed. If an other
script is compiled after bailout, or if a class is linked after bailout, the
recorded errors will be attached to it.

This change fixes this by freeing recorded errors before executing shutdown
functions.

Fixes phpGH-8063
arnaud-lb added a commit that referenced this issue Apr 22, 2022
Recorded errors may be attached to the wrong cached script when a fatal error
occurs during recording. This happens because the fatal error will cause a
bailout, which may prevent the recorded errors from being freed. If an other
script is compiled after bailout, or if a class is linked after bailout, the
recorded errors will be attached to it.

This change fixes this by freeing recorded errors before executing shutdown
functions.

Fixes GH-8063
@arnaud-lb
Copy link
Member

Fixed in #8297

@sahilpurav
Copy link

I'm on PHP 8.3.9 and I'm still receiving the error. The log says: include(): Failed opening '/var/www/dragonglass/crm/vendor/composer/../laravel/framework/src/Illuminate/Foundation/Bootstrap/BootProviders.php' for inclusion (include_path='.:/usr/share/php')

As soon as I hit opcache_reset(). It fixes the issue. It happens only after deployment. I have added opcache_reset() as a part of our deployment script. It does not break everytime. It happens randomly after 10-15 deployments.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants