httpd-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Ralf S. Engelschall" <...@engelschall.com>
Subject [PATCH] Fix module execution order for DSO situation (take 2)
Date Mon, 04 May 1998 14:10:25 GMT

Fix module execution order for DSO situation (take 2)
=====================================================

I've already posted the first version of this patch a while ago but I was not
sure if the realloc() stuff from this version was the way we should do it.
After thinking a week more I finally had the "Oh yeah" effect: The
re-allocation is not needed because we already have DYNAMIC_MODULE_LIMIT which
is already used to allocate the space for dynamically added modules. I've
changed my patch to use this and now I'm happy with it and we can really
consider it to be comitted before 1.3b7/1.3.0.

The patch is essential for 1.3b7/1.3.0 because it makes sure the module
execution order is correct even when some modules are loaded under runtime
(`LoadModule') via the DSO mechanism.  The way to fix this is to reconstruct
the module list in httpd.conf via ClearModuleList+AddModule directives. But
currently this is broken because the ap_preloaded_modules is used as the basis
for loaded modules. This is bogus and a relict from times where no DSO
mechanism exists.

The patch does the following:

     1. The list of loaded modules is now a dynamically allocated one
        and not the original statically list from modules.c
     2. The loaded modules are now correctly setup by LoadModule for
        later use by the AddModule command.
     3. When the DSO mechanism for modules is used APACI's `install'
        target now enables all created `LoadModule' lines per default because
        this is both already expected by the user _and_ needed to avoid
        confusion with the next point and reduces the Makefile.tmpl complexity
     4. When the DSO mechanism for modules is used, APACI's `install'
        target now additionally makes sure the module list is reconstructed
        via a complete `ClearModuleList+AddModule...' entry.
     5. The support tool `apxs' now also makes sure an AddModule command
        is added in addition to the LoadModule command.
     6. The modules.c generation was extended to now contain two
        comments to make sure no one is confused by the confusing terminology
        of loading/linking (we use load=link+load & link=activate instead of
        the obvious load=activate & link=link :-( )

This way now there is no longer a difference under execution time between
statically and dynamically linked modules.

                                       Ralf S. Engelschall
                                       rse@engelschall.com
                                       www.engelschall.com
Index: INSTALL
===================================================================
RCS file: /e/apache/REPOS/apache-1.3/INSTALL,v
retrieving revision 1.23
diff -u -r1.23 INSTALL
--- INSTALL	1998/04/30 11:32:03	1.23
+++ INSTALL	1998/05/02 11:27:06
@@ -237,20 +237,10 @@
                  module because there are variants like `--enable-shared=all'
                  which should not imply `--enable-module=all'.  
 
-         Note 2: The --enable-shared option only implies the preparation of
-                 LoadModule commands in the httpd.conf file for the "make
-                 install" procedure. But these LoadModule lines are per
-                 default out-commented. So, --enable-shared does not imply the
-                 automatic use of the module. The only exception are modules
-                 which have to be enabled because of their usage in the
-                 provided sample configuration. To actually use DSO-based
-                 modules you have to uncomment the corresponding LoadModule
-                 lines in PREFIX/etc/httpd.conf after "make install".
-
-         Note 3: Per default the DSO mechanism is globally disabled, i.e. no
+         Note 2: Per default the DSO mechanism is globally disabled, i.e. no
                  modules are build as shared objects.
 
-         Note 4: The usage of any --enable-shared option automatically implies
+         Note 3: The usage of any --enable-shared option automatically implies
                  a --enable-module=so option because the bootstrapping module
                  mod_so is always needed for DSO support.
 
Index: Makefile.tmpl
===================================================================
RCS file: /e/apache/REPOS/apache-1.3/Makefile.tmpl,v
retrieving revision 1.30
diff -u -r1.30 Makefile.tmpl
--- Makefile.tmpl	1998/05/03 10:22:26	1.30
+++ Makefile.tmpl	1998/05/04 12:11:22
@@ -124,19 +124,6 @@
 #   forwarding arguments
 MFWD = root=$(root)
 
-#   list of shared objects which have to _ALWAYS_ be enabled
-#   per default in the config file because of the directives used
-#   in these default files.
-so_mods_in_conf = \
-config_log_module|\
-mime_module|\
-negotiation_module|\
-autoindex_module|\
-dir_module|\
-userdir_module|\
-access_module|\
-setenvif_module
-
 ## ==================================================================
 ##                              Targets
 ## ==================================================================
@@ -258,12 +245,19 @@
 			echo "$(INSTALL_SCRIPT) $(TOP)/$(SRC)/$$mod $(root)$(libexecdir)/$$file"; \
 			$(INSTALL_SCRIPT) $(TOP)/$(SRC)/$$mod $(root)$(libexecdir)/$$file; \
 			name=`$(TOP)/$(AUX)/fmn.sh $(TOP)/$(SRC)/$$mod`; \
-			prefix="#"; case $$name in $(so_mods_in_conf) ) prefix="" ;; esac; \
-			echo dummy | awk '{ printf("%sLoadModule %-18s %s\n", \
-			prefix, modname, modpath); }' \
-			prefix="$$prefix" modname="$$name" \
-			modpath="$(libexecdir_relative)$$file" >>$(SRC)/.apaci.install.conf; \
+			echo dummy | awk '{ printf("LoadModule %-18s %s\n", modname, modpath); }' \
+			modname="$$name" modpath="$(libexecdir_relative)$$file" >>$(SRC)/.apaci.install.conf;
\
 		done; \
+		echo "" >>$(SRC)/.apaci.install.conf; \
+		echo "#  Reconstruction of the complete module list from all available modules" >>$(SRC)/.apaci.install.conf;
\
+		echo "#  (static and shared ones) to achieve correct module execution order." >>$(SRC)/.apaci.install.conf;
\
+		echo "#  [WHENEVER YOU CHANGE THE LOADMODULE SECTION ABOVE UPDATE THIS, TOO]" >>$(SRC)/.apaci.install.conf;
\
+		echo "ClearModuleList" >>$(SRC)/.apaci.install.conf; \
+		egrep "^[ 	]*(Add|Shared)Module" $(SRC)/Configuration.apaci |\
+		sed	-e 's:SharedModule:AddModule:' \
+			-e 's:modules/[^/]*/::' \
+			-e 's:[ 	]lib: mod_:' \
+			-e 's:\.[soa]*$$:.c:' >>$(SRC)/.apaci.install.conf; \
 	fi
 	@echo "<=== [programs]"
 
Index: src/CHANGES
===================================================================
RCS file: /e/apache/REPOS/apache-1.3/src/CHANGES,v
retrieving revision 1.815
diff -u -r1.815 CHANGES
--- CHANGES	1998/05/04 06:58:02	1.815
+++ CHANGES	1998/05/04 14:09:10
@@ -1,4 +1,27 @@
 Changes with Apache 1.3b7
+  
+  *) Make sure the module execution order is correct even when some modules
+     are loaded under runtime (`LoadModule') via the DSO mechanism:
+     1. The list of loaded modules is now a dynamically allocated one
+        and not the original statically list from modules.c
+     2. The loaded modules are now correctly setup by LoadModule for
+        later use by the AddModule command.
+     3. When the DSO mechanism for modules is used APACI's `install'
+        target now enables all created `LoadModule' lines per default because
+        this is both already expected by the user _and_ needed to avoid
+        confusion with the next point and reduces the Makefile.tmpl complexity
+     4. When the DSO mechanism for modules is used, APACI's `install'
+        target now additionally makes sure the module list is reconstructed
+        via a complete `ClearModuleList+AddModule...' entry.
+     5. The support tool `apxs' now also makes sure an AddModule command
+        is added in addition to the LoadModule command.
+     6. The modules.c generation was extended to now contain two
+        comments to make sure no one is confused by the confusing terminology
+        of loading/linking (we use load=link+load & link=activate instead of
+        the obvious load=activate & link=link :-( )
+     This way now there is no longer a difference under execution time between
+     statically and dynamically linked modules.
+     [Ralf S. Engelschall]
 
   *) Ronald Tschalaer's Accept-Encoding patch - preserve the "x-" in
      the encoding type from the Accept-Encoding header (if it's there)
@@ -32,6 +55,7 @@
   *) WIN32: Make roots of filesystems (e.g. c:/) work. [Ben Laurie]
      PR#1558
 
+>>>>>>> 1.815
   *) PORT: Various porting changes to support AIX 3.2, 4.1.5, 4.2 and 4.3.
      Additionally the checks for finding the vendor DSO library were moved
      from mod_so.c to Configure because first it needs $PLAT etc. and second
Index: src/include/http_config.h
===================================================================
RCS file: /e/apache/REPOS/apache-1.3/src/include/http_config.h,v
retrieving revision 1.81
diff -u -r1.81 http_config.h
--- http_config.h	1998/05/03 17:31:08	1.81
+++ http_config.h	1998/05/04 12:11:33
@@ -303,6 +303,8 @@
 
 API_EXPORT(void) ap_add_module(module *m);
 API_EXPORT(void) ap_remove_module(module *m);
+API_EXPORT(void) ap_add_loaded_module(module *mod);
+API_EXPORT(void) ap_remove_loaded_module(module *mod);
 API_EXPORT(int) ap_add_named_module(const char *name);
 API_EXPORT(void) ap_clear_module_list(void);
 API_EXPORT(const char *) ap_find_module_name(module *m);
@@ -317,6 +319,7 @@
 
 extern module *ap_prelinked_modules[];
 extern module *ap_preloaded_modules[];
+extern module **ap_loaded_modules;
 
 /* For http_main.c... */
 
Index: src/main/http_config.c
===================================================================
RCS file: /e/apache/REPOS/apache-1.3/src/main/http_config.c,v
retrieving revision 1.114
diff -u -r1.114 http_config.c
--- http_config.c	1998/04/13 18:05:10	1.114
+++ http_config.c	1998/05/04 13:54:46
@@ -94,11 +94,12 @@
  */
 static int total_modules = 0;
 /* dynamic_modules is the number of modules that have been added
- * after the pre-linked ones have been set up. It shouldn't be larger
+ * after the pre-loaded ones have been set up. It shouldn't be larger
  * than DYNAMIC_MODULE_LIMIT.
  */
 static int dynamic_modules = 0;
 API_VAR_EXPORT module *top_module = NULL;
+API_VAR_EXPORT module **ap_loaded_modules;
 
 typedef int (*handler_func) (request_rec *);
 typedef void *(*dir_maker_func) (pool *, char *);
@@ -616,20 +617,83 @@
     dynamic_modules--;
 }
 
+API_EXPORT(void) ap_add_loaded_module(module *mod)
+{
+    module **m;
 
-void ap_setup_prelinked_modules()
+    /* 
+     *  Add module pointer to top of chained module list 
+     */
+    ap_add_module(mod);
+
+    /* 
+     *  And module pointer to list of loaded modules 
+     *
+     *  Notes: 1. ap_add_module() would already complain if no more space
+     *            exists for adding a dynamically loaded module
+     *         2. ap_add_module() accepts double-inclusion, so we have
+     *            to accept this, too.
+     */
+    for (m = ap_loaded_modules; *m != NULL; m++)
+        ;
+    *m++ = mod;
+    *m = NULL;
+}
+
+API_EXPORT(void) ap_remove_loaded_module(module *mod)
 {
     module **m;
+    module **m2;
+    int done;
 
-    /* First, set all module indices, and init total_modules.  */
-    total_modules = 0;
-    for (m = ap_preloaded_modules; *m; ++m, ++total_modules) {
-	(*m)->module_index = total_modules;
-    }
+    /* 
+     *  Remove module pointer from chained module list 
+     */
+    ap_remove_module(mod);
 
-    for (m = ap_prelinked_modules; *m; ++m) {
-	ap_add_module(*m);
+    /* 
+     *  Remove module pointer from list of loaded modules
+     *
+     *  Note: 1. We cannot determine if the module was successfully
+     *           removed by ap_remove_module().
+     *        2. We have not to complain explicity when the module
+     *           is not found because ap_remove_module() did it
+     *           for us already.
+     */
+    for (m = m2 = ap_loaded_modules, done = 0; *m2 != NULL; m2++) {
+        if (*m2 == mod && done == 0)
+            done = 1;
+        else
+            *m++ = *m2;
     }
+    *m = NULL;
+}
+
+void ap_setup_prelinked_modules()
+{
+    module **m;
+    module **m2;
+
+    /*
+     *  Initialise total_modules variable and module indices
+     */
+    for (m = ap_preloaded_modules; *m != NULL; m++)
+        (*m)->module_index = total_modules++;
+
+    /* 
+     *  Initialise list of loaded modules
+     */
+    ap_loaded_modules = (module **)malloc(
+        sizeof(module *)*(total_modules+DYNAMIC_MODULE_LIMIT+1));
+    for (m = ap_preloaded_modules, m2 = ap_loaded_modules; *m != NULL; )
+        *m2++ = *m++;
+    *m2 = NULL;
+
+    /*
+     *   Initialize chain of linked (=activate) modules
+     */
+    for (m = ap_prelinked_modules; *m != NULL; m++)
+        ap_add_module(*m);
 }
 
 API_EXPORT(const char *) ap_find_module_name(module *m)
@@ -654,7 +718,7 @@
     module *modp;
     int i = 0;
 
-    for (modp = ap_preloaded_modules[i]; modp; modp = ap_preloaded_modules[++i]) {
+    for (modp = ap_loaded_modules[i]; modp; modp = ap_loaded_modules[++i]) {
 	if (strcmp(modp->name, name) == 0) {
 	    /* Only add modules that are not already enabled.  */
 	    if (modp->next == NULL) {
@@ -1515,12 +1579,12 @@
     const command_rec *pc;
     int n;
 
-    for (n = 0; ap_preloaded_modules[n]; ++n)
-	for (pc = ap_preloaded_modules[n]->cmds; pc && pc->name; ++pc) {
-	    printf("%s (%s)\n", pc->name, ap_preloaded_modules[n]->name);
+    for (n = 0; ap_loaded_modules[n]; ++n)
+	for (pc = ap_loaded_modules[n]->cmds; pc && pc->name; ++pc) {
+	    printf("%s (%s)\n", pc->name, ap_loaded_modules[n]->name);
 	    if (pc->errmsg)
 		printf("\t%s\n", pc->errmsg);
-	    show_overrides(pc, ap_preloaded_modules[n]);
+	    show_overrides(pc, ap_loaded_modules[n]);
 	}
 }
 
@@ -1530,6 +1594,6 @@
     int n;
 
     printf("Compiled-in modules:\n");
-    for (n = 0; ap_preloaded_modules[n]; ++n)
-	printf("  %s\n", ap_preloaded_modules[n]->name);
+    for (n = 0; ap_loaded_modules[n]; ++n)
+	printf("  %s\n", ap_loaded_modules[n]->name);
 }
Index: src/modules/standard/mod_so.c
===================================================================
RCS file: /e/apache/REPOS/apache-1.3/src/modules/standard/mod_so.c,v
retrieving revision 1.24
diff -u -r1.24 mod_so.c
--- mod_so.c	1998/05/02 11:15:13	1.24
+++ mod_so.c	1998/05/02 11:27:20
@@ -170,7 +170,7 @@
         return;
 
     /* remove the module pointer from the core structure */
-    ap_remove_module(modi->modp);
+    ap_remove_loaded_module(modi->modp);
 
     /* unload the module space itself */
     ap_os_dso_unload((ap_os_dso_handle_t)modi->modp->dynamic_load_handle);
@@ -251,7 +251,7 @@
     /* 
      * Add this module to the Apache core structures
      */
-    ap_add_module(modp);
+    ap_add_loaded_module(modp);
 
     /* 
      * Register a cleanup in the config pool (normally pconf). When
Index: src/support/apxs.pl
===================================================================
RCS file: /e/apache/REPOS/apache-1.3/src/support/apxs.pl,v
retrieving revision 1.4
diff -u -r1.4 apxs.pl
--- apxs.pl	1998/04/15 09:46:57	1.4
+++ apxs.pl	1998/04/17 08:41:29
@@ -369,8 +369,9 @@
     ##
 
     #   determine installation commands
-    #   and corresponding LoadModule directives
+    #   and corresponding LoadModule/AddModule directives
     my @lmd = ();
+    my @amd = ();
     my @cmds = ();
     my $f;
     foreach $f (@args) {
@@ -383,7 +384,8 @@
         push(@cmds, "cp $f $CFG_LIBEXECDIR/$t");
         push(@cmds, "chmod 755 $CFG_LIBEXECDIR/$t");
 
-        #   determine module name
+        #   determine module symbolname and filename
+        my $filename = '';
         if ($name eq 'unknown') {
             $name = '';
             my $base = $f;
@@ -394,11 +396,15 @@
                 close(FP);
                 if ($content =~ m|.*module\s+(?:MODULE_VAR_EXPORT\s+)?([a-zA-Z0-9_]+)_module\s*=\s*.*|s)
{
                     $name = "$1";
+                    $filename = "$base.c";
+                    $filename =~ s|^[^/]+/||;
                 }
             }
             if ($name eq '') {
                 if ($base =~ m|.*mod_([a-zA-Z0-9_]+)\..+|) {
                     $name = "$1";
+                    $filename = $base;
+                    $filename =~ s|^[^/]+/||;
                 }
             }
             if ($name eq '') {
@@ -407,16 +413,20 @@
                 exit(1);
             }
         }
+        if ($filename eq '') {
+            $filename = "mod_${name}.c";
+        }
         my $dir = $CFG_LIBEXECDIR;
         $dir =~ s|^$CFG_PREFIX/?||;
         $dir =~ s|(.)$|$1/|;
         push(@lmd, sprintf("LoadModule %-18s %s", "${name}_module", "$dir$t"));
+        push(@amd, sprintf("AddModule %s", $filename));
     }
 
     #   execute the commands
     &execute_cmds(@cmds);
 
-    #   activate module via LoadModule directive
+    #   activate module via LoadModule/AddModule directive
     if ($opt_a or $opt_A) {
         if (not -f "$CFG_SYSCONFDIR/httpd.conf") {
             print "apxs:Error: Config file $CFG_SYSCONFDIR/httpd.conf not found\n";
@@ -444,6 +454,15 @@
                  $lmd =~ m|LoadModule\s+(.+?)_module.*|;
                  my $what = $opt_A ? "preparing" : "activating";
                  print STDERR "[$what module `$1' in $CFG_SYSCONFDIR/httpd.conf]\n";
+            }
+        }
+        my $amd;
+        foreach $amd (@amd) {
+            if ($content !~ m|\n#?\s*$amd|) {
+                 my $c = '';
+                 $c = '#' if ($opt_A);
+                 $content =~ s|^(.*\n#?\s*AddModule\s+[^\n]+\n)|$1$c$amd\n|sg;
+                 $update = 1;
             }
         }
         if ($update) {

Mime
View raw message