1
0
mirror of https://github.com/php/php-src.git synced 2026-03-24 00:02:20 +01:00

opcache: Improve error messages when “temporarily enabling OPcache” (#19619)

* opcache: Do not emit “temporary enabling” message when OPcache is already active

An easy way to accidentally enable OPcache “temporarily” is by using
`php_admin_value[opcache.enable]=1` within a FPM pool’s configuration, since
the `php_admin_value` settings mostly behave like settings in php.ini, with
many OPcache INI settings being a notable exception.

As long as OPcache is already enabled within php.ini (or simply by default),
emitting a warning for `php_admin_value[opcache.enable]=1` or similar is going
to be confusing, since is not actually temporarily enabling anything.

A follow-up commit will also try to detect this kind of incorrect configuration
and try to provide better advice for cases where OPcache is actually not yet
enabled.

* opcache: Improve error message when OPcache is enabled dynamically

The error message will now advice on the `php_admin_value[opcache.enable]=1`
mistake. It will also send the message to OPcache’s logging facility instead of
the regular error handling logic during startup so that it will not be made
available to `error_get_last()`, since it is related to a specific request and
thus not actionable by a script either.

php/php-src#19146 made a related change to `opcache.memory_consumption`.

* opcache: Fix typo in warning message

* opcache: Use more formal language in warning message
This commit is contained in:
Tim Düsterhus
2025-08-31 00:32:42 +02:00
committed by GitHub
parent 3bf495b5cc
commit 2a086e4e73
4 changed files with 106 additions and 2 deletions

View File

@@ -0,0 +1,24 @@
--TEST--
Dynamically setting opcache.enable does not warn when noop
--INI--
opcache.enable=1
opcache.enable_cli=1
--EXTENSIONS--
opcache
--FILE--
<?php
echo "Should not warn:", PHP_EOL;
ini_set('opcache.enable', 1);
echo "Disabling:", PHP_EOL;
ini_set('opcache.enable', 0);
echo "Should warn:", PHP_EOL;
ini_set('opcache.enable', 1);
?>
--EXPECTF--
Should not warn:
Disabling:
Should warn:
Warning: Zend OPcache can't be temporarily enabled (it may be only disabled until the end of request) in %s on line %d

View File

@@ -0,0 +1,18 @@
--TEST--
Dynamically setting opcache.enable warns when not a noop
--INI--
opcache.enable=0
opcache.enable_cli=1
--EXTENSIONS--
opcache
--FILE--
<?php
echo "Should warn, since the INI was initialized to 0:", PHP_EOL;
ini_set('opcache.enable', 1);
?>
--EXPECTF--
Should warn, since the INI was initialized to 0:
Warning: Zend OPcache can't be temporarily enabled (it may be only disabled until the end of request) in %s on line %d

View File

@@ -159,10 +159,23 @@ static ZEND_INI_MH(OnEnable)
stage == ZEND_INI_STAGE_DEACTIVATE) {
return OnUpdateBool(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage);
} else {
/* It may be only temporary disabled */
/* It may be only temporarily disabled */
bool *p = (bool *) ZEND_INI_GET_ADDR();
if (zend_ini_parse_bool(new_value)) {
zend_error(E_WARNING, ACCELERATOR_PRODUCT_NAME " can't be temporary enabled (it may be only disabled till the end of request)");
if (*p) {
/* Do not warn if OPcache is enabled, as the update would be a noop anyways. */
return SUCCESS;
}
if (stage == ZEND_INI_STAGE_ACTIVATE) {
if (strcmp(sapi_module.name, "fpm-fcgi") == 0) {
zend_accel_error(ACCEL_LOG_WARNING, ACCELERATOR_PRODUCT_NAME " can't be temporarily enabled. Are you using php_admin_value[opcache.enable]=1 in an individual pool's configuration?");
} else {
zend_accel_error(ACCEL_LOG_WARNING, ACCELERATOR_PRODUCT_NAME " can't be temporarily enabled (it may be only disabled until the end of request)");
}
} else {
zend_error(E_WARNING, ACCELERATOR_PRODUCT_NAME " can't be temporarily enabled (it may be only disabled until the end of request)");
}
return FAILURE;
} else {
*p = 0;

View File

@@ -0,0 +1,49 @@
--TEST--
Setting opcache.enable via php_admin_value fails gracefully
--SKIPIF--
<?php include "skipif.inc"; ?>
--FILE--
<?php
require_once "tester.inc";
$cfg = <<<EOT
[global]
error_log = {{FILE:LOG}}
[unconfined]
listen = {{ADDR}}
pm = static
pm.max_children = 1
catch_workers_output = yes
php_admin_value[opcache.enable] = On
php_admin_flag[display_errors] = On
php_admin_flag[display_startup_errors] = On
php_admin_flag[log_errors] = On
EOT;
$code = <<<EOT
<?php
var_dump(error_get_last());
EOT;
$tester = new FPM\Tester($cfg, $code);
$tester->start(iniEntries: [
'opcache.enable' => '0',
'opcache.log_verbosity_level' => '2',
]);
$tester->expectLogStartNotices();
$tester->expectLogPattern("/Zend OPcache can't be temporarily enabled. Are you using php_admin_value\\[opcache.enable\\]=1 in an individual pool's configuration?/");
echo $tester
->request()
->getBody();
$tester->terminate();
$tester->close();
?>
--EXPECT--
NULL
--CLEAN--
<?php
require_once "tester.inc";
FPM\Tester::clean();
?>