]> granicus.if.org Git - apache/commitdiff
Add new ap_reserve_module_slots/ap_reserve_module_slots_directive API,
authorStefan Fritsch <sf@apache.org>
Mon, 25 Apr 2011 19:22:04 +0000 (19:22 +0000)
committerStefan Fritsch <sf@apache.org>
Mon, 25 Apr 2011 19:22:04 +0000 (19:22 +0000)
necessary if a module (like mod_perl) registers additional modules later than the
EXEC_ON_READ phase.

Tested by: Torsten Foertsch <torsten foertsch gmx net>

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1096569 13f79535-47bb-0310-9956-ffa450edef68

CHANGES
docs/manual/developer/new_api_2_4.xml
include/ap_mmn.h
include/http_config.h
include/http_core.h
modules/generators/mod_cgid.c
server/config.c
server/core.c

diff --git a/CHANGES b/CHANGES
index f3ccce8cad3a506318b374b2a7e414ebec24e6be..794d52509d0b508e8eaa383771be9b131b2262d6 100644 (file)
--- 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 <torsten foertsch gmx net>]
 
index 3a7fe956a926365a103c5c051365e7d3cd2bb1d1..b3bdf13bd489ab9e02275923d4595d0446ae579f 100644 (file)
       <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>
 
index 711f2cb74af601453359a9b4169d4c4609090580..c8817769d80c28679fa8f4868f78fbd124e2f7ec 100644 (file)
  *                         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
index 6d8e18503799fdea8c46e2563c9a55ac06e78480..80956c0f1f5da310991261090b6689c5d02871b7 100644 (file)
@@ -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
index ba66de84002a80539fd10154cadce2af1d207d9f..7b822a52243ce52e7f6a9717cb0a5b007370812d 100644 (file)
@@ -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);
 
 /* ----------------------------------------------------------------------
  *
index 651c6a0d2dd60633ca0ac46fefa9b27c2d064f14..91d290e9ce9ebbc9876b4f4a5e21229106d883c3 100644 (file)
@@ -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;
index 85dd7093fa28239e9134793453bb2c677d247b18..3d30b5bdad83cab431a13cdb4088ac0ccdff711b 100644 (file)
@@ -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));
+}
index b5c9905b8ce88f645fd8983e62685fc132197599..4d4bb8ce017b2930e515aa63953995c8b63acf39 100644 (file)
@@ -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