You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@httpd.apache.org by "Ralf S. Engelschall" <rs...@engelschall.com> on 1998/02/23 17:46:04 UTC

[PATCH] Fix RewriteMap programs

Fix RewriteMap programs
-----------------------

The below patch tries to fix the long-standing bug (see e.g. PR#1029) where
RewriteMap programs are broken under SunOS and FreeBSD because these systems
hate locking a pipe directly. To avoid this problem I introduce a RewriteLock
directive which when present defines a lockfile for mod_rewrite. This lockfile
then is used to synchronize the protocol between the multiple server processes
and the single rewriting map program.

I tested it now under my FreeBSD 2.1.5 box and it seems to work fine.  I was
able to use a rewriting map program again and all of my parallel
ZeusBench-generated requests were correctly transformed. But it needs review
and testing by others.
                                       Ralf S. Engelschall
                                       rse@engelschall.com
                                       www.engelschall.com

Index: mod_rewrite.h
===================================================================
RCS file: /e/apache/REPOS/apache-1.3/src/modules/standard/mod_rewrite.h,v
retrieving revision 1.37
diff -u -r1.37 mod_rewrite.h
--- mod_rewrite.h	1998/02/23 08:27:39	1.37
+++ mod_rewrite.h	1998/02/23 16:00:51
@@ -136,17 +136,9 @@
 #ifdef WIN32
 #undef USE_FCNTL
 #define USE_LOCKING
+#include <sys/locking.h>
 #endif
 
-    /* The locking support for the RewriteMap programs:
-     * Locking a pipe to the child works fine under most
-     * Unix derivates, but braindead SunOS 4.1.x has 
-     * problems with this approach...
-     */
-#define USE_PIPE_LOCKING 1
-#ifdef SUNOS4
-#undef USE_PIPE_LOCKING
-#endif
 
 /*
 **
@@ -265,6 +257,8 @@
     char         *rewritelogfile;  /* the RewriteLog filename */
     int           rewritelogfp;    /* the RewriteLog open filepointer */
     int           rewriteloglevel; /* the RewriteLog level of verbosity */
+    char         *rewritelockfile; /* the RewriteLock filename */
+    int           rewritelockfp;   /* the RewriteLock open filepointer */
     array_header *rewritemaps;     /* the RewriteMap entries */
     array_header *rewriteconds;    /* the RewriteCond entries (temporary) */
     array_header *rewriterules;    /* the RewriteRule entries */
@@ -339,6 +333,8 @@
 static const char *cmd_rewritemap     (cmd_parms *cmd, void *dconf, char *a1,
                                        char *a2);
 
+static const char *cmd_rewritelock(cmd_parms *cmd, void *dconf, char *a1);
+
 static const char *cmd_rewritebase(cmd_parms *cmd, rewrite_perdir_conf *dconf,
                                    char *a1);
 
@@ -409,6 +405,11 @@
 static void  rewritelog(request_rec *r, int level, const char *text, ...)
 			__attribute__((format(printf,3,4)));
 static char *current_logtime(request_rec *r);
+
+    /* rewritinf lockfile support */
+static void open_rewritelock(server_rec *s, pool *p);
+static void rewritelock_take(request_rec *r);
+static void rewritelock_free(request_rec *r);
 
     /* program map support */
 static void  run_rewritemap_programs(server_rec *s, pool *p);
Index: mod_rewrite.c
===================================================================
RCS file: /e/apache/REPOS/apache-1.3/src/modules/standard/mod_rewrite.c,v
retrieving revision 1.68
diff -u -r1.68 mod_rewrite.c
--- mod_rewrite.c	1998/02/23 15:18:50	1.68
+++ mod_rewrite.c	1998/02/23 16:04:32
@@ -112,9 +112,6 @@
     /* now our own stuff ... */
 #include "mod_rewrite.h"
 
-#ifdef USE_LOCKING
-#include <sys/locking.h>
-#endif 
 
 
 /*
@@ -172,6 +169,8 @@
       "a URL-applied regexp-pattern and a substitution URL" },
     { "RewriteMap",      cmd_rewritemap,      NULL, RSRC_CONF,   TAKE2, 
       "a mapname and a filename" },
+    { "RewriteLock",     cmd_rewritelock,     NULL, RSRC_CONF,   TAKE1,
+      "the filename of a lockfile used for inter-process synchronisation"},
     { "RewriteLog",      cmd_rewritelog,      NULL, RSRC_CONF,   TAKE1, 
       "the filename of the rewriting logfile" },
     { "RewriteLogLevel", cmd_rewriteloglevel, NULL, RSRC_CONF,   TAKE1, 
@@ -250,6 +249,8 @@
     a->rewritelogfile  = NULL;
     a->rewritelogfp    = -1;
     a->rewriteloglevel = 1;
+    a->rewritelockfile = NULL;
+    a->rewritelockfp   = -1;
     a->rewritemaps     = make_array(p, 2, sizeof(rewritemap_entry));
     a->rewriteconds    = make_array(p, 2, sizeof(rewritecond_entry));
     a->rewriterules    = make_array(p, 2, sizeof(rewriterule_entry));
@@ -272,6 +273,10 @@
     a->rewritelogfp    = base->rewritelogfp != -1   ?
                          base->rewritelogfp : overrides->rewritelogfp;
     a->rewriteloglevel = overrides->rewriteloglevel;
+    a->rewritelockfile = base->rewritelockfile != NULL ?
+                         base->rewritelockfile : overrides->rewritelockfile;
+    a->rewritelockfp   = base->rewritelockfp != -1   ?
+                         base->rewritelockfp : overrides->rewritelockfp;
 
     if (a->options & OPTION_INHERIT) {
         a->rewritemaps  = append_arrays(p, overrides->rewritemaps,
@@ -490,6 +495,18 @@
     return NULL;
 }
 
+static const char *cmd_rewritelock(cmd_parms *cmd, void *dconf, char *a1)
+{
+    rewrite_server_conf *sconf;
+
+    sconf = (rewrite_server_conf *)
+            get_module_config(cmd->server->module_config, &rewrite_module);
+
+    sconf->rewritelockfile = a1;
+
+    return NULL;
+}
+
 static const char *cmd_rewritebase(cmd_parms *cmd, rewrite_perdir_conf *dconf,
                                    char *a1)
 {
@@ -856,10 +873,12 @@
 {
     /* step through the servers and
      * - open each rewriting logfile 
+     * - open each rewriting lockfile 
      * - open the RewriteMap prg:xxx programs
      */
     for (; s; s = s->next) {
         open_rewritelog(s, p);
+        open_rewritelock(s, p);
         run_rewritemap_programs(s, p);
     }
 
@@ -2635,10 +2654,8 @@
     char c;
     int i;
 
-    /* lock the channel */
-#ifdef USE_PIPE_LOCKING
-    fd_lock(fpin);
-#endif
+    /* take the lock */
+    rewritelock_take(r);
 
     /* write out the request key */
     write(fpin, key, strlen(key));
@@ -2653,10 +2670,8 @@
     }
     buf[i] = '\0';
 
-    /* unlock the channel */
-#ifdef USE_PIPE_LOCKING
-    fd_unlock(fpin);
-#endif
+    /* give the lock back */
+    rewritelock_free(r);
 
     if (strcasecmp(buf, "NULL") == 0)
         return NULL;
@@ -2775,7 +2790,7 @@
     if (*(conf->rewritelogfile) == '\0')
         return;
     if (conf->rewritelogfp > 0)
-        return; /* virtual log shared w/main server */
+        return; /* virtual log shared w/ main server */
 
     fname = server_root_relative(p, conf->rewritelogfile);
     
@@ -2918,6 +2933,70 @@
 }
 
 
+
+
+/*
+** +-------------------------------------------------------+
+** |                                                       |
+** |              rewriting lockfile support
+** |                                                       |
+** +-------------------------------------------------------+
+*/
+
+static void open_rewritelock(server_rec *s, pool *p)
+{
+    rewrite_server_conf *conf;
+    char *fname;
+    int    rewritelock_flags = ( O_WRONLY|O_APPEND|O_CREAT );
+#ifdef WIN32
+    mode_t rewritelock_mode  = ( _S_IREAD|_S_IWRITE );
+#else
+    mode_t rewritelock_mode  = ( S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH );
+#endif
+  
+    conf = get_module_config(s->module_config, &rewrite_module);
+    
+    if (conf->rewritelockfile == NULL)
+        return; 
+    if (*(conf->rewritelockfile) == '\0')
+        return;
+    if (conf->rewritelockfp > 0)
+        return; /* virtual log shared w/ main server */
+
+    fname = server_root_relative(p, conf->rewritelockfile);
+    
+    if ((conf->rewritelockfp = popenf(p, fname, rewritelock_flags, 
+                                      rewritelock_mode)) < 0) {
+        perror("open");
+        fprintf(stderr, 
+                "mod_rewrite: could not open RewriteLock file %s.\n",
+                fname);
+        exit(1);
+    }
+    return;
+}
+
+static void rewritelock_take(request_rec *r)
+{
+    rewrite_server_conf *conf;
+
+    conf = get_module_config(r->server->module_config, &rewrite_module);
+
+    if (conf->rewritelockfp != -1)
+        fd_lock(conf->rewritelockfp);
+    return;
+}
+
+static void rewritelock_free(request_rec *r)
+{
+    rewrite_server_conf *conf;
+
+    conf = get_module_config(r->server->module_config, &rewrite_module);
+
+    if (conf->rewritelockfp != -1)
+        fd_unlock(conf->rewritelockfp);
+    return;
+}
 
 
 /*