On Tuesday, April 12, 2011 18:24:28 William A. Rowe Jr. wrote: > Suggestion - an EXEC_ON_READ 'DynamicModulesMax' directive, which would > let us conf_vector_length = total_modules + dyn_modules_max; after the > read_config, and finally lock down conf_vector_length = total_modules; > at the end of post_config. WDYT?
The attached patch implements the DynamicModulesMax directive. It can appear anywhere in the config file but is best placed *before* any LoadModule directive. Up to post_config the number of prelinked modules plus DynamicModulesMax is used as conf_vector_length. In core_post_config the length is then settled on total_modules. Torsten Förtsch -- Need professional modperl support? Hire me! (http://foertsch.name) Like fantasy? http://kabatinte.net
Index: server/config.c =================================================================== --- server/config.c (revision 1094174) +++ server/config.c (working copy) @@ -181,22 +181,22 @@ static int total_modules = 0; /* dynamic_modules is the number of modules that have been added - * after the pre-loaded ones have been set up. It shouldn't be larger - * than DYNAMIC_MODULE_LIMIT. + * after the pre-loaded ones have been set up. It should be at most + * dynamic_modules_max. */ static int dynamic_modules = 0; -/* The maximum possible value for total_modules, i.e. number of static - * modules plus DYNAMIC_MODULE_LIMIT. +/* The maximum possible value for dynamic_modules. Shouldn't be larger than + * DYNAMIC_MODULE_LIMIT. */ -static int max_modules = 0; +static int dynamic_modules_max; /* The number of elements we need to alloc for config vectors. Before loading - * of dynamic modules, we must be liberal and set this to max_modules. After - * loading of dynamic modules, we can trim it down to total_modules. On - * restart, reset to max_modules. + * of dynamic modules, we must be liberal and set this to the largest possible + * value (number of prelinked modules + dynamic_modules_max). After loading of + * dynamic modules, we can trim it down to total_modules. */ -static int conf_vector_length = 0; +static int conf_vector_length; AP_DECLARE_DATA module *ap_top_module = NULL; AP_DECLARE_DATA module **ap_loaded_modules=NULL; @@ -234,6 +234,22 @@ * overridden). */ +AP_DECLARE(void) ap_set_dynamic_modules_max(int lim) +{ + dynamic_modules_max = lim; + conf_vector_length = dynamic_modules_max + total_modules - dynamic_modules; +} + +AP_DECLARE(int) ap_get_dynamic_modules_max(void) +{ + return dynamic_modules_max; +} + +AP_DECLARE(void) ap_settle_module_count(void) +{ + conf_vector_length = total_modules; +} + static ap_conf_vector_t *create_empty_config(apr_pool_t *p) { void *conf_vector = apr_pcalloc(p, sizeof(void *) * conf_vector_length); @@ -542,7 +558,7 @@ } if (m->module_index == -1) { - if (dynamic_modules >= DYNAMIC_MODULE_LIMIT) { + if (dynamic_modules >= dynamic_modules_max) { return apr_psprintf(p, "Module \"%s\" could not be loaded, " "because the dynamic module limit was " "reached. Please increase " @@ -740,8 +756,7 @@ for (m = ap_preloaded_modules; *m != NULL; m++) (*m)->module_index = total_modules++; - max_modules = total_modules + DYNAMIC_MODULE_LIMIT + 1; - conf_vector_length = max_modules; + ap_set_dynamic_modules_max(DYNAMIC_MODULE_LIMIT); /* * Initialise list of loaded modules and short names @@ -2255,12 +2270,6 @@ } -static apr_status_t reset_conf_vector_length(void *dummy) -{ - conf_vector_length = max_modules; - return APR_SUCCESS; -} - AP_DECLARE(server_rec*) ap_read_config(process_rec *process, apr_pool_t *ptemp, const char *filename, ap_directive_t **conftree) @@ -2272,6 +2281,7 @@ return s; } + ap_set_dynamic_modules_max(DYNAMIC_MODULE_LIMIT); init_config_globals(p); /* All server-wide config files now have the SAME syntax... */ @@ -2309,14 +2319,6 @@ return NULL; } - /* - * We have loaded the dynamic modules. From now on we know exactly how - * long the config vectors need to be. - */ - conf_vector_length = total_modules; - apr_pool_cleanup_register(p, NULL, reset_conf_vector_length, - apr_pool_cleanup_null); - error = process_command_config(s, ap_server_post_read_config, conftree, p, ptemp); Index: server/core.c =================================================================== --- server/core.c (revision 1094174) +++ server/core.c (working copy) @@ -3167,6 +3167,19 @@ } #endif +static const char *set_dynamic_modules_max(cmd_parms *cmd, void *dummy, + const char *arg) +{ + const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_LOC_FILE); + + if (err != NULL) { + return err; + } + + ap_set_dynamic_modules_max(atoi(arg)); + return NULL; +} + #ifdef RLIMIT_CPU static const char *set_limit_cpu(cmd_parms *cmd, void *conf_, const char *arg, const char *arg2) @@ -3753,6 +3766,9 @@ "body"), AP_INIT_RAW_ARGS("Mutex", ap_set_mutex, NULL, RSRC_CONF, "mutex (or \"default\") and mechanism"), +AP_INIT_TAKE1("DynamicModulesMax", set_dynamic_modules_max, NULL, + RSRC_CONF | EXEC_ON_READ, + "Limit on the number of dynamically loadable modules"), /* System Resource Controls */ #ifdef RLIMIT_CPU @@ -4175,6 +4191,12 @@ "or other system security module is loaded."); return !OK; } + + /* + * We have loaded the dynamic modules. From now on we know exactly how + * long the config vectors need to be. + */ + ap_settle_module_count(); return OK; } Index: modules/core/mod_so.c =================================================================== --- modules/core/mod_so.c (revision 1094174) +++ modules/core/mod_so.c (working copy) @@ -113,8 +113,6 @@ so_server_conf *soc; soc = (so_server_conf *)apr_pcalloc(p, sizeof(so_server_conf)); - soc->loaded_modules = apr_array_make(p, DYNAMIC_MODULE_LIMIT, - sizeof(ap_module_symbol_t)); return (void *)soc; } @@ -179,6 +177,13 @@ */ sconf = (so_server_conf *)ap_get_module_config(cmd->server->module_config, &so_module); + + if (!sconf->loaded_modules) { + sconf->loaded_modules = apr_array_make(cmd->pool, + ap_get_dynamic_modules_max(), + sizeof(ap_module_symbol_t)); + } + modie = (ap_module_symbol_t *)sconf->loaded_modules->elts; for (i = 0; i < sconf->loaded_modules->nelts; i++) { modi = &modie[i]; @@ -339,13 +344,15 @@ sconf = (so_server_conf *)ap_get_module_config(s->module_config, &so_module); - modie = (ap_module_symbol_t *)sconf->loaded_modules->elts; + if (sconf->loaded_modules) { + modie = (ap_module_symbol_t *)sconf->loaded_modules->elts; - for (i = 0; i < sconf->loaded_modules->nelts; i++) { - modi = &modie[i]; - if (modi->name != NULL && strcmp(modi->name, modname) == 0) { - return modi->modp; - } + for (i = 0; i < sconf->loaded_modules->nelts; i++) { + modi = &modie[i]; + if (modi->name != NULL && strcmp(modi->name, modname) == 0) { + return modi->modp; + } + } } return NULL; } @@ -378,12 +385,14 @@ } } - modie = (ap_module_symbol_t *)sconf->loaded_modules->elts; - for (i = 0; i < sconf->loaded_modules->nelts; i++) { - modi = &modie[i]; - if (modi->name != NULL) { - apr_file_printf(out, " %s (shared)\n", modi->name); - } + if (sconf->loaded_modules) { + modie = (ap_module_symbol_t *)sconf->loaded_modules->elts; + for (i = 0; i < sconf->loaded_modules->nelts; i++) { + modi = &modie[i]; + if (modi->name != NULL) { + apr_file_printf(out, " %s (shared)\n", modi->name); + } + } } } Index: modules/generators/mod_cgid.c =================================================================== --- modules/generators/mod_cgid.c (revision 1094174) +++ modules/generators/mod_cgid.c (working copy) @@ -421,7 +421,7 @@ } /* handle module indexes and such */ - rconf = (void **) apr_pcalloc(r->pool, sizeof(void *) * (total_modules + DYNAMIC_MODULE_LIMIT)); + rconf = (void **)ap_create_request_config(r->pool); temp_core = (core_request_config *)apr_palloc(r->pool, sizeof(core_module)); rconf[req->core_module_index] = (void *)temp_core; Index: include/http_config.h =================================================================== --- include/http_config.h (revision 1094174) +++ include/http_config.h (working copy) @@ -472,6 +472,25 @@ typedef struct ap_conf_vector_t ap_conf_vector_t; /** + * Set the dynamic module limit. Used by the DynamicModulesMax directive. + * Also adjusts conf_vector_length. + * @param lim The limit. + */ +AP_DECLARE(void) ap_set_dynamic_modules_max(int lim); + +/** + * Get the dynamic module limit. + * @return The limit. + */ +AP_DECLARE(int) ap_get_dynamic_modules_max(void); + +/** + * When the number of modules has settled (in post_config) this function + * adjusts the conf_vector_length. + */ +AP_DECLARE(void) ap_settle_module_count(void); + +/** * Generic accessors for other modules to get at their own module-specific * data * @param cv The vector in which the modules configuration is stored.