From fa7ff1268e2f1e5850104f6f75510a20bdb1d172 Mon Sep 17 00:00:00 2001 From: Pavel Gushcha Date: Fri, 9 Oct 2026 17:12:07 +0000 Subject: [PATCH 1/2] Fix opcache.interned_strings_buffer being 0 in threads started later (ZTS) Since GH-23309 OnUpdateInternedStringsBuffer() rejects any change once OPcache is set up, to catch diverging php_admin_value settings of FPM pools. Under ZTS every thread started after OPcache's startup re-applies the INI entries with ZEND_INI_STAGE_STARTUP into its own, zeroed zend_accel_globals; the handler rejects that as well, logs a warning for every new thread and leaves ZCG(accel_directives). interned_strings_buffer at 0 in that thread (e.g. opcache_get_configuration() reports 0 under FrankenPHP and Apache mod_php with threaded MPMs). Accept the value at ZEND_INI_STAGE_STARTUP: it is the value the shared memory was set up with. Changes at later stages (FPM pools use ZEND_INI_STAGE_ACTIVATE) are still rejected. --- ext/opcache/zend_accelerator_module.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ext/opcache/zend_accelerator_module.c b/ext/opcache/zend_accelerator_module.c index 23192e8950bf..6a9170992d10 100644 --- a/ext/opcache/zend_accelerator_module.c +++ b/ext/opcache/zend_accelerator_module.c @@ -93,7 +93,8 @@ static ZEND_INI_MH(OnUpdateMemoryConsumption) static ZEND_INI_MH(OnUpdateInternedStringsBuffer) { - if (accel_startup_ok) { + /* Under ZTS every new thread re-applies the startup value (ZEND_INI_STAGE_STARTUP) */ + if (accel_startup_ok && stage != ZEND_INI_STAGE_STARTUP) { if (strcmp(sapi_module.name, "fpm-fcgi") == 0) { zend_accel_error(ACCEL_LOG_WARNING, "opcache.interned_strings_buffer cannot be changed when OPcache is already set up. Are you using php_admin_value[opcache.interned_strings_buffer] in an individual pool's configuration?\n"); } else { From 51df7a06ffecbb0f2aa1c3807bf010281ed248b5 Mon Sep 17 00:00:00 2001 From: Pavel Gushcha Date: Tue, 13 Oct 2026 17:37:11 +0000 Subject: [PATCH 2/2] Address review comment Explain why accepting the value at ZEND_INI_STAGE_STARTUP is safe and why NTS is not affected. --- ext/opcache/zend_accelerator_module.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/ext/opcache/zend_accelerator_module.c b/ext/opcache/zend_accelerator_module.c index 6a9170992d10..902d69374bb7 100644 --- a/ext/opcache/zend_accelerator_module.c +++ b/ext/opcache/zend_accelerator_module.c @@ -93,7 +93,11 @@ static ZEND_INI_MH(OnUpdateMemoryConsumption) static ZEND_INI_MH(OnUpdateInternedStringsBuffer) { - /* Under ZTS every new thread re-applies the startup value (ZEND_INI_STAGE_STARTUP) */ + /* Under ZTS, every thread started later re-applies the INI entries at + * ZEND_INI_STAGE_STARTUP to fill its own globals. Accepting that is safe: the + * value comes from the global INI directives, so it is the one OPcache was + * set up with. NTS does not have this problem: STARTUP handlers run before + * accel_startup_ok is set, and accel_shutdown() clears it again. */ if (accel_startup_ok && stage != ZEND_INI_STAGE_STARTUP) { if (strcmp(sapi_module.name, "fpm-fcgi") == 0) { zend_accel_error(ACCEL_LOG_WARNING, "opcache.interned_strings_buffer cannot be changed when OPcache is already set up. Are you using php_admin_value[opcache.interned_strings_buffer] in an individual pool's configuration?\n");