Add opcache_preloading() internal function

Add a C function, opcache_preloading(), that returns true during
preloading. Extensions can use this to detect preloading, not only during
compilation/execution, but also in RINIT()/RSHUTDOWN().

Since opcache currently doesn't install any header, I'm adding a new one:
zend_accelerator_api.h. Header name is based on other files in ext/opcache.

Closes GH-19288
This commit is contained in:
Arnaud Le Blanc 2025-07-29 14:37:13 +02:00
parent 3088d64068
commit 32290b3529
No known key found for this signature in database
12 changed files with 124 additions and 1 deletions

View file

@ -4845,6 +4845,8 @@ static zend_result accel_finish_startup_preload(bool in_child)
bool old_reset_signals = SIGG(reset);
#endif
ZCG(preloading) = true;
sapi_module.activate = NULL;
sapi_module.deactivate = NULL;
sapi_module.register_server_variables = NULL;
@ -4926,6 +4928,8 @@ static zend_result accel_finish_startup_preload(bool in_child)
sapi_module.ub_write = orig_ub_write;
sapi_module.flush = orig_flush;
ZCG(preloading) = false;
sapi_activate();
return ret;

View file

@ -220,6 +220,7 @@ typedef struct _zend_accel_globals {
#endif
void *preloaded_internal_run_time_cache;
size_t preloaded_internal_run_time_cache_size;
bool preloading;
/* preallocated shared-memory block to save current script */
void *mem;
zend_persistent_script *current_persistent_script;

View file

@ -325,6 +325,7 @@ PHP_NEW_EXTENSION([opcache], m4_normalize([
shared_alloc_mmap.c
shared_alloc_posix.c
shared_alloc_shm.c
zend_accelerator_api.c
zend_accelerator_blacklist.c
zend_accelerator_debug.c
zend_accelerator_hash.c
@ -361,3 +362,5 @@ AS_VAR_IF([PHP_OPCACHE_JIT], [yes], [
])
PHP_ADD_MAKEFILE_FRAGMENT([$ext_srcdir/jit/Makefile.frag])
])
PHP_INSTALL_HEADERS([ext/opcache], [zend_accelerator_api.h])

View file

@ -4,6 +4,7 @@ PHP_OPCACHE="yes";
ZEND_EXTENSION('opcache', "\
ZendAccelerator.c \
zend_accelerator_api.c \
zend_accelerator_blacklist.c \
zend_accelerator_debug.c \
zend_accelerator_hash.c \
@ -68,3 +69,5 @@ if (PHP_OPCACHE_JIT == "yes") {
}
ADD_FLAG('CFLAGS_OPCACHE', "/I " + configure_module_dirname);
PHP_INSTALL_HEADERS("ext/opcache", "zend_accelerator_api.h");

View file

@ -0,0 +1,3 @@
<?php
printf("%s: %d\n", __FILE__, zend_test_opcache_preloading());
?>

View file

@ -0,0 +1,19 @@
--TEST--
opcache_preloading() api 001
--INI--
opcache.enable=1
opcache.enable_cli=1
opcache.preload={PWD}/opcache_preloading.inc
--SKIPIF--
<?php
if (PHP_OS_FAMILY == 'Windows') die('skip Preloading is not supported on Windows');
?>
--FILE--
<?php
printf("%s: %d\n", __FILE__, zend_test_opcache_preloading());
?>
--EXPECTF--
%sopcache_preloading.inc: 1
%sopcache_preloading_001.php: 0

View file

@ -0,0 +1,23 @@
--TEST--
opcache_preloading() api 002
--INI--
opcache.enable=1
opcache.enable_cli=1
opcache.preload={PWD}/opcache_preloading.inc
opcache.preload_user={ENV:TEST_NON_ROOT_USER}
--EXTENSIONS--
posix
--SKIPIF--
<?php
if (PHP_OS_FAMILY == 'Windows') die('skip Preloading is not supported on Windows');
if (posix_geteuid() !== 0) die('skip Test needs root user');
?>
--FILE--
<?php
printf("%s: %d\n", __FILE__, zend_test_opcache_preloading());
?>
--EXPECTF--
%sopcache_preloading.inc: 1
%sopcache_preloading_002.php: 0

View file

@ -0,0 +1,23 @@
/*
+----------------------------------------------------------------------+
| Zend OPcache |
+----------------------------------------------------------------------+
| Copyright (c) The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| https://www.php.net/license/3_01.txt |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
*/
#include "zend_accelerator_api.h"
#include "ZendAccelerator.h"
ZEND_API bool opcache_preloading(void)
{
return ZCG(preloading);
}

View file

@ -0,0 +1,29 @@
/*
+----------------------------------------------------------------------+
| Zend OPcache |
+----------------------------------------------------------------------+
| Copyright (c) The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| https://www.php.net/license/3_01.txt |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
*/
#ifndef ZEND_ACCELERATOR_API_H
#define ZEND_ACCELERATOR_API_H
#include "Zend/zend_portability.h"
BEGIN_EXTERN_C()
/* Returns true during preloading */
ZEND_API bool opcache_preloading(void);
END_EXTERN_C()
#endif /* ZEND_ACCELERATOR_API_H */

View file

@ -14,6 +14,8 @@
+----------------------------------------------------------------------+
*/
#include "ext/opcache/zend_accelerator_api.h"
#include "zend_API.h"
#include "zend_modules.h"
#include "zend_types.h"
#ifdef HAVE_CONFIG_H
@ -1645,3 +1647,10 @@ static PHP_FUNCTION(zend_test_gh18756)
zend_mm_gc(heap);
zend_mm_shutdown(heap, true, false);
}
static PHP_FUNCTION(zend_test_opcache_preloading)
{
ZEND_PARSE_PARAMETERS_NONE();
RETURN_BOOL(opcache_preloading());
}

View file

@ -338,6 +338,8 @@ function zend_test_override_libxml_global_state(): void {}
function zend_test_compile_to_ast(string $str): string {}
function zend_test_gh18756(): void {}
function zend_test_opcache_preloading(): bool {}
}
namespace ZendTestNS {

View file

@ -1,5 +1,5 @@
/* This is a generated file, edit the .stub.php file instead.
* Stub hash: 073039fa0d9c41eb842f6944eb4acfc9217103cf */
* Stub hash: 781677c7ada9095af9c964cf86ce6ba63a52a930 */
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_zend_test_array_return, 0, 0, IS_ARRAY, 0)
ZEND_END_ARG_INFO()
@ -185,6 +185,8 @@ ZEND_END_ARG_INFO()
#define arginfo_zend_test_gh18756 arginfo_zend_test_void_return
#define arginfo_zend_test_opcache_preloading arginfo_zend_test_is_pcre_bundled
#define arginfo_ZendTestNS2_namespaced_func arginfo_zend_test_is_pcre_bundled
#define arginfo_ZendTestNS2_namespaced_deprecated_func arginfo_zend_test_void_return
@ -325,6 +327,7 @@ static ZEND_FUNCTION(zend_test_is_zend_ptr);
static ZEND_FUNCTION(zend_test_log_err_debug);
static ZEND_FUNCTION(zend_test_compile_to_ast);
static ZEND_FUNCTION(zend_test_gh18756);
static ZEND_FUNCTION(zend_test_opcache_preloading);
static ZEND_FUNCTION(ZendTestNS2_namespaced_func);
static ZEND_FUNCTION(ZendTestNS2_namespaced_deprecated_func);
static ZEND_FUNCTION(ZendTestNS2_ZendSubNS_namespaced_func);
@ -452,6 +455,7 @@ static const zend_function_entry ext_functions[] = {
ZEND_FE(zend_test_log_err_debug, arginfo_zend_test_log_err_debug)
ZEND_FE(zend_test_compile_to_ast, arginfo_zend_test_compile_to_ast)
ZEND_FE(zend_test_gh18756, arginfo_zend_test_gh18756)
ZEND_FE(zend_test_opcache_preloading, arginfo_zend_test_opcache_preloading)
#if (PHP_VERSION_ID >= 80400)
ZEND_RAW_FENTRY(ZEND_NS_NAME("ZendTestNS2", "namespaced_func"), zif_ZendTestNS2_namespaced_func, arginfo_ZendTestNS2_namespaced_func, 0, NULL, NULL)
#else