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 for DSO situation (take 2)
Date Tue, 21 Apr 1998 18:59:32 GMT

Fix module execution for DSO situation
======================================

I've still not seen any votes except Lars' one for this patch, so I've cleaned
it up a little bit more and post it again. Because the current situation has
too much side-effects I really want to commit it now.

The patch 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 loaded modules are now correctly setup by LoadModule for
      later use by the AddModule command
   2. 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
   3. 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.
   4. The support tool `apxs' now also makes sure an AddModule command
      is added in addition to the LoadModule command.

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.17
diff -u -r1.17 INSTALL
--- INSTALL	1998/04/21 16:00:32	1.17
+++ INSTALL	1998/04/21 16:05:59
@@ -234,20 +234,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.23
diff -u -r1.23 Makefile.tmpl
--- Makefile.tmpl	1998/04/21 17:33:58	1.23
+++ Makefile.tmpl	1998/04/21 18:51:40
@@ -112,19 +112,6 @@
 clean-support     = @clean_support@
 distclean-support = @distclean_support@
 
-#   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
 ## ==================================================================
@@ -246,12 +233,19 @@
 			echo "$(INSTALL_SCRIPT) $(SRC)/$$mod $(libexecdir)/$$file"; \
 			$(INSTALL_SCRIPT) $(SRC)/$$mod $(libexecdir)/$$file; \
 			name=`$(AUX)/fmn.sh $(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" >>.install.conf; \
+			echo dummy | awk '{ printf("LoadModule %-18s %s\n", modname, modpath); }' \
+			modname="$$name" modpath="$(libexecdir_relative)$$file" >>.install.conf; \
 		done; \
+		echo "" >>.install.conf; \
+		echo "#  Reconstruction of the complete module list from all available modules" >>.install.conf;
\
+		echo "#  (static and shared ones) to achieve correct module execution order." >>.install.conf;
\
+		echo "#  [WHENEVER YOU CHANGE THE LOADMODULE SECTION ABOVE UPDATE THIS, TOO]" >>.install.conf;
\
+		echo "ClearModuleList" >>.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:' >>.install.conf; \
 	fi
 	@echo "<=== [programs]"
 
Index: src/CHANGES
===================================================================
RCS file: /e/apache/REPOS/apache-1.3/src/CHANGES,v
retrieving revision 1.786
diff -u -r1.786 CHANGES
--- CHANGES	1998/04/21 17:34:00	1.786
+++ CHANGES	1998/04/21 18:49:39
@@ -1,4 +1,21 @@
 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 loaded modules are now correctly setup by LoadModule for
+        later use by the AddModule command
+     2. 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
+     3. 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.
+     4. The support tool `apxs' now also makes sure an AddModule command
+        is added in addition to the LoadModule command.
+     This way now there is no longer a difference under execution time between
+     statically and dynamically linked modules.
+     [Ralf S. Engelschall]
 
   *) Fix the path to the ScoreBoardFile in the install-config target, too.
      [Ralf S. Engelschall] PR#2105
Index: src/include/http_config.h
===================================================================
RCS file: /e/apache/REPOS/apache-1.3/src/include/http_config.h,v
retrieving revision 1.80
diff -u -r1.80 http_config.h
--- http_config.h	1998/04/13 18:11:51	1.80
+++ http_config.h	1998/04/17 06:50:24
@@ -299,6 +299,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);
@@ -313,6 +315,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/04/21 14:46:41
@@ -99,6 +99,7 @@
  */
 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,86 @@
     dynamic_modules--;
 }
 
+API_EXPORT(void) ap_add_loaded_module(module *mod)
+{
+    int n;
+    module **m;
 
+    /* 
+     * Insert module pointer into list of loaded modules
+     */
+    n = 0;
+    for (m = ap_loaded_modules; *m; m++) 
+        n++;
+    ap_loaded_modules = (module **)realloc(ap_loaded_modules,
+                                           sizeof(module *)*(n+2));
+    ap_loaded_modules[n++] = mod;
+    ap_loaded_modules[n] = NULL;
+
+    /* 
+     * Add module pointer to top of chained module list 
+     */
+    ap_add_module(mod);
+}
+
+API_EXPORT(void) ap_remove_loaded_module(module *mod)
+{
+    int n;
+    module **m;
+    module **m2;
+
+    /* 
+     *  Remove module pointer from chained module list 
+     */
+    ap_remove_module(mod);
+
+    /* 
+     *  Remove module pointer from list of loaded modules
+     */
+    n = 0;
+    for (m = ap_loaded_modules; *m; m++) 
+        n++;
+    for (m = m2 = ap_loaded_modules; *m2; m2++)
+        if (*m2 != mod)
+            *m++ = *m2;
+    if (m < m2) {
+        *m = NULL;
+        ap_loaded_modules = (module **)realloc(ap_loaded_modules,
+                                               sizeof(module *)*n);
+    }
+    else {
+        ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, NULL,
+             "Cannot remove module %s: "
+             "not found in list of loaded modules", mod->name);
+    }
+}
+
 void ap_setup_prelinked_modules()
 {
     module **m;
 
-    /* First, set all module indices, and init total_modules.  */
+    /* 
+     * 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;
-    }
+    for (m = ap_preloaded_modules; *m; ++m, ++total_modules)
+        (*m)->module_index = total_modules;
 
-    for (m = ap_prelinked_modules; *m; ++m) {
-	ap_add_module(*m);
-    }
+    /* 
+     * Second, initialize the list of loaded 
+     * modules with the preloaded ones
+     */
+    ap_loaded_modules = (module **)malloc(sizeof(module *)*(total_modules+1));
+    memcpy(ap_loaded_modules, ap_preloaded_modules, 
+           sizeof(module *)*(total_modules+1));
+
+    /*
+     * Third, chain these module structures
+     * to form the list of active modules
+     */
+    for (m = ap_prelinked_modules; *m; ++m)
+        ap_add_module(*m);
 }
 
 API_EXPORT(const char *) ap_find_module_name(module *m)
@@ -654,7 +721,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 +1582,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 +1597,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.22
diff -u -r1.22 mod_so.c
--- mod_so.c	1998/04/14 10:58:24	1.22
+++ mod_so.c	1998/04/16 15:33:14
@@ -192,7 +192,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);
@@ -273,7 +273,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