diff --git a/frankenphp.c b/frankenphp.c index af116437d..fab1501b6 100644 --- a/frankenphp.c +++ b/frankenphp.c @@ -33,7 +33,10 @@ ZEND_TSRMLS_CACHE_DEFINE() #endif -static const char *MODULES_TO_RELOAD[] = {"filter", "session", NULL}; +#define INITIAL_MODULES_CAPACITY 8 + +static const char *MODULES_TO_RELOAD[] = {"filter", "session"}; +frankenphp_modules_to_reload modules_to_reload = {NULL, 0, 0}; frankenphp_version frankenphp_get_version() { return (frankenphp_version){ @@ -115,18 +118,42 @@ static void frankenphp_release_temporary_streams() { ZEND_HASH_FOREACH_END(); } +static void init_modules_to_reload(void) { + if (modules_to_reload.names != NULL) { + return; + } + + size_t length = sizeof MODULES_TO_RELOAD / sizeof *MODULES_TO_RELOAD; + + size_t capacity = length > 0 ? length * 2 : INITIAL_MODULES_CAPACITY; + modules_to_reload.names = malloc(capacity * sizeof(char *)); + if (!modules_to_reload.names) { + return; // TODO: handle this as an error + } + + for (size_t i = 0; i < length; i++) { + modules_to_reload.names[i] = strdup(MODULES_TO_RELOAD[i]); + } + + modules_to_reload.length = length; + modules_to_reload.capacity = capacity; +} + /* Adapted from php_request_shutdown */ static void frankenphp_worker_request_shutdown() { /* Flush all output buffers */ zend_try { php_output_end_all(); } zend_end_try(); - /* TODO: store the list of modules to reload in a global module variable */ - const char **module_name; + init_modules_to_reload(); + zend_module_entry *module; - for (module_name = MODULES_TO_RELOAD; *module_name; module_name++) { - if ((module = zend_hash_str_find_ptr(&module_registry, *module_name, - strlen(*module_name)))) { + for (size_t i = 0; i < modules_to_reload.length; i++) { + module = + zend_hash_str_find_ptr(&module_registry, modules_to_reload.names[i], + strlen(modules_to_reload.names[i])); + + if (module && module->request_shutdown_func) { module->request_shutdown_func(module->type, module->module_number); } } @@ -144,6 +171,37 @@ static void frankenphp_worker_request_shutdown() { zend_set_memory_limit(PG(memory_limit)); } +/* API for extensions to register their modules to reload */ +bool frankenphp_register_module_to_reload(const char *module_name) { + if (module_name == NULL) { + return false; + } + + init_modules_to_reload(); + + for (size_t i = 0; i < modules_to_reload.length; i++) { + if (strcmp(modules_to_reload.names[i], module_name) == 0) { + return true; + } + } + + if (modules_to_reload.length >= modules_to_reload.capacity) { + size_t new_capacity = modules_to_reload.capacity * 2; + const char **new_names = + realloc(modules_to_reload.names, new_capacity * sizeof(char *)); + if (!new_names) { + return false; // Out of memory + } + modules_to_reload.names = new_names; + modules_to_reload.capacity = new_capacity; + } + + modules_to_reload.names[modules_to_reload.length] = strdup(module_name); + modules_to_reload.length++; + + return true; +} + // shutdown the dummy request that starts the worker script bool frankenphp_shutdown_dummy_request(void) { if (SG(server_context) == NULL) { @@ -223,13 +281,15 @@ static int frankenphp_worker_request_startup() { } } - /* TODO: store the list of modules to reload in a global module variable */ - const char **module_name; + init_modules_to_reload(); + + /* Reload modules */ zend_module_entry *module; - for (module_name = MODULES_TO_RELOAD; *module_name; module_name++) { - if ((module = zend_hash_str_find_ptr(&module_registry, *module_name, - strlen(*module_name))) && - module->request_startup_func) { + for (size_t i = 0; i < modules_to_reload.length; i++) { + module = + zend_hash_str_find_ptr(&module_registry, modules_to_reload.names[i], + strlen(modules_to_reload.names[i])); + if (module && module->request_startup_func) { module->request_startup_func(module->type, module->module_number); } } diff --git a/frankenphp.h b/frankenphp.h index 7839bcf7e..1b61778ef 100644 --- a/frankenphp.h +++ b/frankenphp.h @@ -46,6 +46,12 @@ typedef struct frankenphp_config { } frankenphp_config; frankenphp_config frankenphp_get_config(); +typedef struct { + const char **names; + size_t length; + size_t capacity; +} frankenphp_modules_to_reload; + int frankenphp_new_main_thread(int num_threads); bool frankenphp_new_php_thread(uintptr_t thread_index); @@ -91,4 +97,6 @@ void frankenphp_register_bulk( ht_key_value_pair auth_type, ht_key_value_pair remote_ident, ht_key_value_pair request_uri); +bool frankenphp_register_module_to_reload(const char *module_name); + #endif