From 364d0ce3f62293d13d584a6c47fd7bc0a4d525b9 Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Sat, 1 Jan 2022 14:17:04 +0100 Subject: [PATCH 1/2] Don't involve PHP in Apache mpm_winnt control process Apache mpm_winnt uses a single control process which launches a single child process which in turn creates threads to handle requests. Since the child process is not forked, but rather spawned, and the control process is never involved in request handling, there is no need to power up PHP for the control process. Besides not doing this saves some resources, we no longer have to deal with potential re-attaching to OPcache shared memory which avoids issues due to ASLR, and paves the way to further improvements (such as preloading support for Apache mpm_winnt). --- sapi/apache2handler/sapi_apache2.c | 49 ++++++++++++++++++++---------- 1 file changed, 33 insertions(+), 16 deletions(-) diff --git a/sapi/apache2handler/sapi_apache2.c b/sapi/apache2handler/sapi_apache2.c index 1d85a92ebf4d8..1fb1a2c8e06bc 100644 --- a/sapi/apache2handler/sapi_apache2.c +++ b/sapi/apache2handler/sapi_apache2.c @@ -461,6 +461,30 @@ static int php_pre_config(apr_pool_t *pconf, apr_pool_t *plog, apr_pool_t *ptemp return OK; } +static int php_apache_startup_php() +{ +#ifdef ZTS + int expected_threads; + if (ap_mpm_query(AP_MPMQ_MAX_THREADS, &expected_threads) != APR_SUCCESS) { + expected_threads = 1; + } + + php_tsrm_startup_ex(expected_threads); +# ifdef PHP_WIN32 + ZEND_TSRMLS_CACHE_UPDATE(); +# endif +#endif + + zend_signal_startup(); + + sapi_startup(&apache2_sapi_module); + if (apache2_sapi_module.startup(&apache2_sapi_module) != SUCCESS) { + return DONE; + } + + return OK; +} + static int php_apache_server_startup(apr_pool_t *pconf, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s) { @@ -484,26 +508,13 @@ php_apache_server_startup(apr_pool_t *pconf, apr_pool_t *plog, apr_pool_t *ptemp if (apache2_php_ini_path_override) { apache2_sapi_module.php_ini_path_override = apache2_php_ini_path_override; } -#ifdef ZTS - int expected_threads; - if (ap_mpm_query(AP_MPMQ_MAX_THREADS, &expected_threads) != APR_SUCCESS) { - expected_threads = 1; - } - - php_tsrm_startup_ex(expected_threads); -# ifdef PHP_WIN32 - ZEND_TSRMLS_CACHE_UPDATE(); -# endif -#endif - - zend_signal_startup(); - - sapi_startup(&apache2_sapi_module); - if (apache2_sapi_module.startup(&apache2_sapi_module) != SUCCESS) { +#ifndef PHP_WIN32 + if (php_apache_startup_php() != OK) { return DONE; } apr_pool_cleanup_register(pconf, NULL, php_apache_server_shutdown, apr_pool_cleanup_null); php_apache_add_version(pconf); +#endif return OK; } @@ -750,7 +761,13 @@ zend_first_try { static void php_apache_child_init(apr_pool_t *pchild, server_rec *s) { +#ifndef PHP_WIN32 apr_pool_cleanup_register(pchild, NULL, php_apache_child_shutdown, apr_pool_cleanup_null); +#else + php_apache_startup_php(); + php_apache_add_version(pchild); + apr_pool_cleanup_register(pchild, NULL, php_apache_server_shutdown, apr_pool_cleanup_null); +#endif } #ifdef ZEND_SIGNALS From 3896a87e293e5d612ae758cd80ef34c3974e0647 Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Wed, 19 Feb 2025 13:32:33 +0100 Subject: [PATCH 2/2] Adapt no longer valid comment Since we no longer involve PHP in the parent process, the comment is no longer true for Apache2, but we might still need this wait loop for other servers/SAPIs. --- ext/opcache/shared_alloc_win32.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/opcache/shared_alloc_win32.c b/ext/opcache/shared_alloc_win32.c index 3f0c71a7c6678..cebbb419135ad 100644 --- a/ext/opcache/shared_alloc_win32.c +++ b/ext/opcache/shared_alloc_win32.c @@ -218,7 +218,7 @@ static int create_segments(size_t requested_size, zend_shared_segment ***shared_ void **wanted_mapping_base = default_mapping_base_set; zend_shared_alloc_lock_win32(); - /* Mapping retries: When Apache2 restarts, the parent process startup routine + /* Mapping retries: When the server restarts, the parent process startup routine can be called before the child process is killed. In this case, the mapping will fail and we have to sleep some time (until the child releases the mapping object) and retry.*/ do {