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 <torsten foertsch gmx net>]
<li>Support for mod_request kept_body</li>
<li>Support buffering filter data for async requests</li>
<li>New CONN_STATE values</li>
- <li>Function changes: ap_escape_html updated; ap_unescape_all, ap_escape_path_segment_buffer</li>
+ <li>Function changes: ap_escape_html updated; ap_unescape_all,
+ ap_escape_path_segment_buffer</li>
+ <li>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.</li>
</ul>
</section>
* 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" */
#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
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... */
/**
* @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
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);
/* ----------------------------------------------------------------------
*
}
/* 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;
*/
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;
"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++;
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)
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);
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));
+}
{
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