From: Stefan Fritsch Date: Mon, 25 Apr 2011 19:22:04 +0000 (+0000) Subject: Add new ap_reserve_module_slots/ap_reserve_module_slots_directive API, X-Git-Tag: 2.3.12~35 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=bf07c1867c534e14a60b1a2718c9093929223f6e;p=thirdparty%2Fapache%2Fhttpd.git Add new ap_reserve_module_slots/ap_reserve_module_slots_directive API, necessary if a module (like mod_perl) registers additional modules later than the EXEC_ON_READ phase. Tested by: Torsten Foertsch git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1096569 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/CHANGES b/CHANGES index f3ccce8cad3..794d52509d0 100644 --- a/CHANGES +++ b/CHANGES @@ -2,6 +2,10 @@ Changes with Apache 2.3.12 + *) Add new ap_reserve_module_slots/ap_reserve_module_slots_directive API, + necessary if a module (like mod_perl) registers additional modules late + in the startup phase. [Stefan Fritsch] + *) core: Prevent segfault if DYNAMIC_MODULE_LIMIT is reached. PR 51072. [Torsten Förtsch ] diff --git a/docs/manual/developer/new_api_2_4.xml b/docs/manual/developer/new_api_2_4.xml index 3a7fe956a92..b3bdf13bd48 100644 --- a/docs/manual/developer/new_api_2_4.xml +++ b/docs/manual/developer/new_api_2_4.xml @@ -130,7 +130,11 @@
  • Support for mod_request kept_body
  • Support buffering filter data for async requests
  • New CONN_STATE values
  • -
  • Function changes: ap_escape_html updated; ap_unescape_all, ap_escape_path_segment_buffer
  • +
  • Function changes: ap_escape_html updated; ap_unescape_all, + ap_escape_path_segment_buffer
  • +
  • Modules that load other modules later than the EXEC_ON_READ config + reading stage need to call ap_reserve_module_slots() or + ap_reserve_module_slots_directive() in their pre_config hook.
  • diff --git a/include/ap_mmn.h b/include/ap_mmn.h index 711f2cb74af..c8817769d80 100644 --- a/include/ap_mmn.h +++ b/include/ap_mmn.h @@ -316,6 +316,9 @@ * Axe mpm_note_child_killed hook, change * ap_reclaim_child_process and ap_recover_child_process * interfaces. + * 20110329.1 (2.3.12-dev) Add ap_reserve_module_slots()/ap_reserve_module_slots_directive() + * change AP_CORE_DECLARE to AP_DECLARE: ap_create_request_config() + * change AP_DECLARE to AP_CORE_DECLARE: ap_register_log_hooks() */ #define MODULE_MAGIC_COOKIE 0x41503234UL /* "AP24" */ @@ -323,7 +326,7 @@ #ifndef MODULE_MAGIC_NUMBER_MAJOR #define MODULE_MAGIC_NUMBER_MAJOR 20110329 #endif -#define MODULE_MAGIC_NUMBER_MINOR 0 /* 0...n */ +#define MODULE_MAGIC_NUMBER_MINOR 1 /* 0...n */ /** * Determine if the server's current MODULE_MAGIC_NUMBER is at least a diff --git a/include/http_config.h b/include/http_config.h index 6d8e1850379..80956c0f1f5 100644 --- a/include/http_config.h +++ b/include/http_config.h @@ -988,6 +988,23 @@ AP_DECLARE(void) ap_register_hooks(module *m, apr_pool_t *p); AP_DECLARE(void) ap_fixup_virtual_hosts(apr_pool_t *p, server_rec *main_server); +/** + * Reserve some modules slots for modules loaded by other means than + * EXEC_ON_READ directives. + * Relevant modules should call this in the pre_config stage. + * @param count The number of slots to reserve. + */ +AP_DECLARE(void) ap_reserve_module_slots(int count); + +/** + * Reserve some modules slots for modules loaded by a specific + * non-EXEC_ON_READ config directive. + * This counts how often the given directive is used in the config and calls + * ap_reserve_module_slots() accordingly. + * @param directive The name of the directive + */ +AP_DECLARE(void) ap_reserve_module_slots_directive(const char *directive); + /* For http_request.c... */ /** @@ -995,7 +1012,7 @@ AP_DECLARE(void) ap_fixup_virtual_hosts(apr_pool_t *p, * @param p The pool to allocate the config vector from * @return The config vector */ -AP_CORE_DECLARE(ap_conf_vector_t*) ap_create_request_config(apr_pool_t *p); +AP_DECLARE(ap_conf_vector_t*) ap_create_request_config(apr_pool_t *p); /** * Setup the config vector for per dir module configs diff --git a/include/http_core.h b/include/http_core.h index ba66de84002..7b822a52243 100644 --- a/include/http_core.h +++ b/include/http_core.h @@ -766,7 +766,8 @@ typedef struct { unsigned int min_loglevel; } ap_errorlog_format_item; -AP_DECLARE(void) ap_register_log_hooks(apr_pool_t *p); +AP_CORE_DECLARE(void) ap_register_log_hooks(apr_pool_t *p); +AP_CORE_DECLARE(void) ap_register_config_hooks(apr_pool_t *p); /* ---------------------------------------------------------------------- * diff --git a/modules/generators/mod_cgid.c b/modules/generators/mod_cgid.c index 651c6a0d2dd..91d290e9ce9 100644 --- a/modules/generators/mod_cgid.c +++ b/modules/generators/mod_cgid.c @@ -421,7 +421,7 @@ static apr_status_t get_req(int fd, request_rec *r, char **argv0, char ***env, } /* 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; diff --git a/server/config.c b/server/config.c index 85dd7093fa2..3d30b5bdad8 100644 --- a/server/config.c +++ b/server/config.c @@ -198,6 +198,8 @@ static int max_modules = 0; */ static int conf_vector_length = 0; +static int reserved_module_slots = 0; + AP_DECLARE_DATA module *ap_top_module = NULL; AP_DECLARE_DATA module **ap_loaded_modules=NULL; @@ -548,6 +550,10 @@ AP_DECLARE(const char *) ap_add_module(module *m, apr_pool_t *p, "reached. Please increase " "DYNAMIC_MODULE_LIMIT and recompile.", m->name); } + /* + * If this fails some module forgot to call ap_reserve_module_slots*. + */ + ap_assert(total_modules < conf_vector_length); m->module_index = total_modules++; dynamic_modules++; @@ -2257,10 +2263,36 @@ static server_rec *init_server_config(process_rec *process, apr_pool_t *p) static apr_status_t reset_conf_vector_length(void *dummy) { + reserved_module_slots = 0; conf_vector_length = max_modules; return APR_SUCCESS; } +static int conf_vector_length_pre_config(apr_pool_t *pconf, apr_pool_t *plog, + apr_pool_t *ptemp) +{ + /* + * We have loaded all modules that are loaded by EXEC_ON_READ directives. + * From now on we reduce the size of the config vectors to what we need, + * plus what has been reserved (e.g. by mod_perl) for additional modules + * loaded later on. + * If max_modules is too small, ap_add_module() will abort. + */ + if (total_modules + reserved_module_slots < max_modules) { + conf_vector_length = total_modules + reserved_module_slots; + } + apr_pool_cleanup_register(pconf, NULL, reset_conf_vector_length, + apr_pool_cleanup_null); + return OK; +} + + +AP_CORE_DECLARE(void) ap_register_config_hooks(apr_pool_t *p) +{ + ap_hook_pre_config(conf_vector_length_pre_config, NULL, NULL, + APR_HOOK_REALLY_LAST); +} + AP_DECLARE(server_rec*) ap_read_config(process_rec *process, apr_pool_t *ptemp, const char *filename, ap_directive_t **conftree) @@ -2309,14 +2341,6 @@ AP_DECLARE(server_rec*) ap_read_config(process_rec *process, apr_pool_t *ptemp, 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); @@ -2487,3 +2511,26 @@ AP_DECLARE(void *) ap_retained_data_create(const char *key, apr_size_t size) apr_pool_userdata_set((const void *)retained, key, apr_pool_cleanup_null, ap_pglobal); return retained; } + +static int count_directives_sub(const char *directive, ap_directive_t *current) +{ + int count = 0; + while (current != NULL) { + if (current->first_child != NULL) + count += count_directives_sub(directive, current->first_child); + if (strcasecmp(current->directive, directive) == 0) + count++; + current = current->next; + } + return count; +} + +AP_DECLARE(void) ap_reserve_module_slots(int count) +{ + reserved_module_slots += count; +} + +AP_DECLARE(void) ap_reserve_module_slots_directive(const char *directive) +{ + ap_reserve_module_slots(count_directives_sub(directive, ap_conftree)); +} diff --git a/server/core.c b/server/core.c index b5c9905b8ce..4d4bb8ce017 100644 --- a/server/core.c +++ b/server/core.c @@ -4380,6 +4380,7 @@ static void register_hooks(apr_pool_t *p) { errorlog_hash = apr_hash_make(p); ap_register_log_hooks(p); + ap_register_config_hooks(p); ap_expr_init(p); /* create_connection and pre_connection should always be hooked