diff --git a/NEWS b/NEWS index 8d3a0a2bfea29..e0894ce8666d6 100644 --- a/NEWS +++ b/NEWS @@ -27,6 +27,8 @@ PHP NEWS . Fixed bug GH-11121 (ReflectionFiber segfault). (danog, trowski, bwoebi) - FPM: + . Fixed bug GH-9921 (Loading ext in FPM config does not register module + handlers). (Jakub Zelenka) . Fixed bug GH-12232 (FPM: segfault dynamically loading extension without opcache). (Jakub Zelenka) . Fixed bug #76922 (FastCGI terminates conn after FCGI_GET_VALUES). diff --git a/Zend/zend_API.c b/Zend/zend_API.c index a82e025952bc4..02b015c43b6a7 100644 --- a/Zend/zend_API.c +++ b/Zend/zend_API.c @@ -2383,7 +2383,8 @@ ZEND_API void zend_collect_module_handlers(void) /* {{{ */ post_deactivate_count++; } } ZEND_HASH_FOREACH_END(); - module_request_startup_handlers = (zend_module_entry**)malloc( + module_request_startup_handlers = (zend_module_entry**)realloc( + module_request_startup_handlers, sizeof(zend_module_entry*) * (startup_count + 1 + shutdown_count + 1 + @@ -2415,7 +2416,8 @@ ZEND_API void zend_collect_module_handlers(void) /* {{{ */ } } ZEND_HASH_FOREACH_END(); - class_cleanup_handlers = (zend_class_entry**)malloc( + class_cleanup_handlers = (zend_class_entry**)realloc( + class_cleanup_handlers, sizeof(zend_class_entry*) * (class_count + 1)); class_cleanup_handlers[class_count] = NULL; @@ -2441,7 +2443,9 @@ ZEND_API void zend_startup_modules(void) /* {{{ */ ZEND_API void zend_destroy_modules(void) /* {{{ */ { free(class_cleanup_handlers); + class_cleanup_handlers = NULL; free(module_request_startup_handlers); + module_request_startup_handlers = NULL; zend_hash_graceful_reverse_destroy(&module_registry); } /* }}} */ diff --git a/ext/dl_test/dl_test.c b/ext/dl_test/dl_test.c index 9cfbdf686a3aa..5a5dfee33f5b0 100644 --- a/ext/dl_test/dl_test.c +++ b/ext/dl_test/dl_test.c @@ -90,6 +90,10 @@ PHP_MINIT_FUNCTION(dl_test) zend_register_functions(NULL, php_dl_test_use_register_functions_directly_functions, NULL, type); } + if (getenv("PHP_DL_TEST_MODULE_DEBUG")) { + fprintf(stderr, "DL TEST MINIT\n"); + } + return SUCCESS; } /* }}} */ @@ -104,6 +108,10 @@ static PHP_MSHUTDOWN_FUNCTION(dl_test) UNREGISTER_INI_ENTRIES(); } + if (getenv("PHP_DL_TEST_MODULE_DEBUG")) { + fprintf(stderr, "DL TEST MSHUTDOWN\n"); + } + return SUCCESS; } /* }}} */ @@ -115,6 +123,21 @@ PHP_RINIT_FUNCTION(dl_test) ZEND_TSRMLS_CACHE_UPDATE(); #endif + if (getenv("PHP_DL_TEST_MODULE_DEBUG")) { + fprintf(stderr, "DL TEST RINIT\n"); + } + + return SUCCESS; +} +/* }}} */ + +/* {{{ PHP_RSHUTDOWN_FUNCTION */ +PHP_RSHUTDOWN_FUNCTION(dl_test) +{ + if (getenv("PHP_DL_TEST_MODULE_DEBUG")) { + fprintf(stderr, "DL TEST RSHUTDOWN\n"); + } + return SUCCESS; } /* }}} */ @@ -148,7 +171,7 @@ zend_module_entry dl_test_module_entry = { PHP_MINIT(dl_test), PHP_MSHUTDOWN(dl_test), PHP_RINIT(dl_test), - NULL, + PHP_RSHUTDOWN(dl_test), PHP_MINFO(dl_test), PHP_DL_TEST_VERSION, PHP_MODULE_GLOBALS(dl_test), diff --git a/sapi/fpm/fpm/fpm_php.c b/sapi/fpm/fpm/fpm_php.c index dd6bf9d9d5f10..b88c47671a1ec 100644 --- a/sapi/fpm/fpm/fpm_php.c +++ b/sapi/fpm/fpm/fpm_php.c @@ -77,6 +77,11 @@ static void fpm_php_disable(char *value, int (*zend_disable)(const char *, size_ } /* }}} */ +#define FPM_PHP_INI_ALTERING_ERROR -1 +#define FPM_PHP_INI_APPLIED 1 +#define FPM_PHP_INI_EXTENSION_FAILED 0 +#define FPM_PHP_INI_EXTENSION_LOADED 2 + int fpm_php_apply_defines_ex(struct key_value_s *kv, int mode) /* {{{ */ { @@ -90,45 +95,57 @@ int fpm_php_apply_defines_ex(struct key_value_s *kv, int mode) /* {{{ */ zend_interned_strings_switch_storage(0); php_dl(value, MODULE_PERSISTENT, &zv, 1); zend_interned_strings_switch_storage(1); - return Z_TYPE(zv) == IS_TRUE; + return Z_TYPE(zv) == IS_TRUE ? FPM_PHP_INI_EXTENSION_LOADED : FPM_PHP_INI_EXTENSION_FAILED; } if (fpm_php_zend_ini_alter_master(name, name_len, value, value_len, mode, PHP_INI_STAGE_ACTIVATE) == FAILURE) { - return -1; + return FPM_PHP_INI_ALTERING_ERROR; } if (!strcmp(name, "disable_functions") && *value) { zend_disable_functions(value); - return 1; + return FPM_PHP_INI_APPLIED; } if (!strcmp(name, "disable_classes") && *value) { char *v = strdup(value); PG(disable_classes) = v; fpm_php_disable(v, zend_disable_class); - return 1; + return FPM_PHP_INI_APPLIED; } - return 1; + return FPM_PHP_INI_APPLIED; } /* }}} */ static int fpm_php_apply_defines(struct fpm_worker_pool_s *wp) /* {{{ */ { struct key_value_s *kv; + int apply_result; + bool extension_loaded = false; for (kv = wp->config->php_values; kv; kv = kv->next) { - if (fpm_php_apply_defines_ex(kv, ZEND_INI_USER) == -1) { + apply_result = fpm_php_apply_defines_ex(kv, ZEND_INI_USER); + if (apply_result == FPM_PHP_INI_ALTERING_ERROR) { zlog(ZLOG_ERROR, "Unable to set php_value '%s'", kv->key); + } else if (apply_result == FPM_PHP_INI_EXTENSION_LOADED) { + extension_loaded = true; } } for (kv = wp->config->php_admin_values; kv; kv = kv->next) { - if (fpm_php_apply_defines_ex(kv, ZEND_INI_SYSTEM) == -1) { + apply_result = fpm_php_apply_defines_ex(kv, ZEND_INI_SYSTEM); + if (apply_result == FPM_PHP_INI_ALTERING_ERROR) { zlog(ZLOG_ERROR, "Unable to set php_admin_value '%s'", kv->key); + } else if (apply_result == FPM_PHP_INI_EXTENSION_LOADED) { + extension_loaded = true; } } + if (extension_loaded) { + zend_collect_module_handlers(); + } + return 0; } /* }}} */ diff --git a/sapi/fpm/tests/gh9921-php-value-ext-mod-handlers.phpt b/sapi/fpm/tests/gh9921-php-value-ext-mod-handlers.phpt new file mode 100644 index 0000000000000..a7057373fdf90 --- /dev/null +++ b/sapi/fpm/tests/gh9921-php-value-ext-mod-handlers.phpt @@ -0,0 +1,54 @@ +--TEST-- +FPM: GH-9921 - loading shared ext in FPM config does not register module handlers +--SKIPIF-- + +--FILE-- +start(); +$tester->expectLogStartNotices(); +$tester->request()->expectBody('bool(true)'); +$tester->expectLogPattern('/DL TEST MINIT/'); +$tester->expectLogPattern('/DL TEST RINIT/'); +$tester->expectLogPattern('/DL TEST RSHUTDOWN/'); +$tester->request()->expectBody('bool(true)'); +$tester->expectLogPattern('/DL TEST RINIT/'); +$tester->expectLogPattern('/DL TEST RSHUTDOWN/'); +$tester->terminate(); +$tester->expectLogTerminatingNotices(); +$tester->close(); + +?> +Done +--EXPECT-- +Done +--CLEAN-- + +