You are viewing a plain text version of this content. The canonical link for it is here.
Posted to modperl@perl.apache.org by Doug MacEachern <do...@covalent.net> on 2000/08/16 02:59:06 UTC

Re: Yet more on set_handlers() and new-found problems with lookup_uri()

i think the jist of the problem(s), is that set_handlers() modifies the
configuration structure (the one created at startup from httpd.conf), so
any subrequests will end up with the modified structure (which is not
reset until the end of the request).  this patch implements
{get,set}_handlers in terms of r->per_request_config, which is
unique to each (sub-)request.  if this doesn't fix the problem, it would
really help to have a small test case that i can drop in to see the bug in
action.

Index: src/modules/perl/Apache.xs
===================================================================
RCS file: /home/cvs/modperl/src/modules/perl/Apache.xs,v
retrieving revision 1.103
diff -u -r1.103 Apache.xs
--- src/modules/perl/Apache.xs	2000/08/15 19:36:32	1.103
+++ src/modules/perl/Apache.xs	2000/08/16 00:46:44
@@ -73,12 +73,6 @@
     void (*set_func) (void *, void *, SV *);
 } perl_handler_table;
 
-typedef struct {
-    I32 fill;
-    AV *av;
-    AV **ptr;
-} perl_save_av;
-
 static void set_handler_dir (perl_handler_table *tab, request_rec *r, SV *sv);
 static void set_handler_srv (perl_handler_table *tab, request_rec *r, SV *sv);
 
@@ -101,28 +95,17 @@
     {HandlerDirEntry("PerlFixupHandler", PerlFixupHandler)},
     {HandlerDirEntry("PerlHandler", PerlHandler)},
     {HandlerDirEntry("PerlLogHandler", PerlLogHandler)},
+    {HandlerDirEntry("PerlCleanupHandler", PerlCleanupHandler)},
     { FALSE, NULL }
 };
 
-static void perl_restore_av(void *data)
-{
-    perl_save_av *save_av = (perl_save_av *)data;
-
-    if(save_av->fill != DONE) {
-	AvFILLp(*save_av->ptr) = save_av->fill;
-    }
-    else if(save_av->av != Nullav) {
-	*save_av->ptr = save_av->av;
-    }
-}
-
 static void perl_handler_merge_avs(char *hook, AV **dest)
 {
     int i = 0;
     HV *hv = perl_get_hv("Apache::PerlStackedHandlers", FALSE);
     SV **svp = hv_fetch(hv, hook, strlen(hook), FALSE);
     AV *base;
-    
+
     if(!(svp && SvROK(*svp)))
 	return;
 
@@ -133,45 +116,53 @@
     }
 }
 
+#define avptr_from_offset(ptr, tab) \
+(AV **)((char *)ptr + (int)(long)tab->offset)
+
 static void set_handler_base(void *ptr, perl_handler_table *tab, pool *p, SV *sv) 
 {
-    AV **av = (AV **)((char *)ptr + (int)(long)tab->offset);
+    int do_register_cleanup = 0;
+    AV **av = avptr_from_offset(ptr, tab);
 
-    perl_save_av *save_av = 
-	(perl_save_av *)palloc(p, sizeof(perl_save_av));
-
-    save_av->fill = DONE;
-    save_av->av = Nullav;
-    
-    if((sv == &sv_undef) || (SvIOK(sv) && SvIV(sv) == DONE)) {
-	if(AvTRUE(*av)) {
-	    save_av->fill = AvFILL(*av);
-	    AvFILLp(*av) = -1;
-	}
-    }
-    else if(SvROK(sv) && SvTYPE(SvRV(sv)) == SVt_PVAV) {
-	if(AvTRUE(*av))
-	    save_av->av = av_copy_array(*av);
-	*av = (AV*)SvRV(sv);
-	++SvREFCNT(*av);
+    if ((sv == &sv_undef) || (SvIOK(sv) && SvIV(sv) == DONE)) {
+        if (!*av) {
+            do_register_cleanup = 1;
+        }
+        if (*av && SvREFCNT(*av)) {
+            SvREFCNT_dec(*av);
+        }
+        *av = newAV();
+    }
+    else if (SvROK(sv) && SvTYPE(SvRV(sv)) == SVt_PVAV) {
+        *av = (AV*)SvRV(sv);
+        ++SvREFCNT(*av);
+        do_register_cleanup = 1;
     }
     else {
-	croak("Can't set_handler with that value");
+        croak("Can't set_handler with that value");
+    }
+
+    if (do_register_cleanup) {
+        register_cleanup(p, (void*)*av, mod_perl_cleanup_av, mod_perl_noop);
     }
-    save_av->ptr = av;
-    register_cleanup(p, save_av, perl_restore_av, mod_perl_noop);
 }
 
-static void set_handler_dir(perl_handler_table *tab, request_rec *r, SV *sv)
+void set_handler_dir(perl_handler_table *tab, request_rec *r, SV *sv)
 {
-    dPPDIR; 
-    set_handler_base((void*)cld, tab, r->pool, sv);
+    dPPREQ;
+    if (!cfg->dir_cfg) {
+        cfg->dir_cfg = perl_create_dir_config(r->pool, r->uri);
+    }
+    set_handler_base((void*)cfg->dir_cfg, tab, r->pool, sv);
 }
 
 static void set_handler_srv(perl_handler_table *tab, request_rec *r, SV *sv)
 {
-    dPSRV(r->server); 
-    set_handler_base((void*)cls, tab, r->pool, sv);
+    dPPREQ;
+    if (!cfg->srv_cfg) {
+        cfg->srv_cfg = perl_create_server_config(r->pool, NULL);
+    }
+    set_handler_base((void*)cfg->srv_cfg, tab, r->pool, sv);
 }
 
 static perl_handler_table *perl_handler_lookup(char *name)
@@ -185,29 +176,45 @@
     return NULL;
 }
 
-
 static SV *get_handlers(request_rec *r, char *hook)
 {
     AV *avcopy;
     AV **av;
+    dPPREQ;
     dPPDIR;
     dPSRV(r->server);
     void *ptr;
     perl_handler_table *tab = perl_handler_lookup(hook);
 
-    if(!tab) return Nullsv;
+    if (!tab) {
+        return Nullsv;
+    }
 
-    if(tab->type == PER_DIR_CONFIG)
-	ptr = (void*)cld;
-    else
-	ptr = (void*)cls;
+    if (tab->type == PER_DIR_CONFIG) {
+        if (cfg->dir_cfg && *avptr_from_offset(cfg->dir_cfg, tab)) {
+            ptr = (void*)cfg->dir_cfg;
+        }
+        else {
+            ptr = (void*)cld;
+        }
+    }
+    else {
+        if (cfg->srv_cfg && *avptr_from_offset(cfg->srv_cfg, tab)) {
+            ptr = (void*)cfg->srv_cfg;
+        }
+        else {
+            ptr = (void*)cls;
+        }
+    }
 
-    av = (AV **)((char *)ptr + (int)(long)tab->offset);
+    av = avptr_from_offset(ptr, tab);
 
-    if(*av) 
+    if (*av) {
 	avcopy = av_copy_array(*av);
-    else
-	avcopy = newAV();
+    }
+    else {
+        avcopy = newAV();
+    }
 
     perl_handler_merge_avs(hook, &avcopy);
 
Index: src/modules/perl/mod_perl.c
===================================================================
RCS file: /home/cvs/modperl/src/modules/perl/mod_perl.c,v
retrieving revision 1.124
diff -u -r1.124 mod_perl.c
--- src/modules/perl/mod_perl.c	2000/08/15 19:36:33	1.124
+++ src/modules/perl/mod_perl.c	2000/08/16 00:46:44
@@ -891,7 +891,8 @@
     }
 
     cfg->setup_env = 1;
-    PERL_CALLBACK("PerlHandler", cld->PerlHandler);
+    PERL_CALLBACK("PerlHandler",
+                  PERL_REQ_DIR_HANDLER(cfg, cld, PerlHandler));
     cfg->setup_env = 0;
 
     FREETMPS;
@@ -965,16 +966,26 @@
 {
     dSTATUS;
     dPSRV(r->server);
+    dPPREQ;
+
+    if (!cfg) {
+	cfg = perl_create_request_config(r->pool, r->server);
+	set_module_config(r->request_config, &perl_module, cfg);
+    }
+
 #if MODULE_MAGIC_NUMBER > 19980270
     if(r->parsed_uri.scheme && r->parsed_uri.hostname && do_proxy(r)) {
 	r->proxyreq = 1;
 	r->uri = r->unparsed_uri;
     }
 #endif
+
 #ifdef PERL_INIT
-    PERL_CALLBACK("PerlInitHandler", cls->PerlInitHandler);
+    PERL_CALLBACK("PerlInitHandler",
+                  PERL_REQ_SRV_HANDLER(cfg, cls, PerlInitHandler));
 #endif
-    PERL_CALLBACK("PerlPostReadRequestHandler", cls->PerlPostReadRequestHandler);
+    PERL_CALLBACK("PerlPostReadRequestHandler",
+                  PERL_REQ_SRV_HANDLER(cfg, cls, PerlPostReadRequestHandler));
     return status;
 }
 #endif
@@ -984,7 +995,9 @@
 {
     dSTATUS;
     dPSRV(r->server);
-    PERL_CALLBACK("PerlTransHandler", cls->PerlTransHandler);
+    dPPREQ;
+    PERL_CALLBACK("PerlTransHandler",
+                  PERL_REQ_SRV_HANDLER(cfg, cls, PerlTransHandler));
     return status;
 }
 #endif
@@ -994,12 +1007,13 @@
 {
     dSTATUS;
     dPPDIR;
+    dPPREQ;
 #ifdef PERL_INIT
     PERL_CALLBACK("PerlInitHandler", 
-			 cld->PerlInitHandler);
+                  PERL_REQ_DIR_HANDLER(cfg, cld, PerlInitHandler));
 #endif
     PERL_CALLBACK("PerlHeaderParserHandler", 
-			 cld->PerlHeaderParserHandler);
+                  PERL_REQ_DIR_HANDLER(cfg, cld, PerlHeaderParserHandler));
     return status;
 }
 #endif
@@ -1009,7 +1023,9 @@
 {
     dSTATUS;
     dPPDIR;
-    PERL_CALLBACK("PerlAuthenHandler", cld->PerlAuthenHandler);
+    dPPREQ;
+    PERL_CALLBACK("PerlAuthenHandler",
+                  PERL_REQ_DIR_HANDLER(cfg, cld, PerlAuthenHandler));
     return status;
 }
 #endif
@@ -1019,7 +1035,9 @@
 {
     dSTATUS;
     dPPDIR;
-    PERL_CALLBACK("PerlAuthzHandler", cld->PerlAuthzHandler);
+    dPPREQ;
+    PERL_CALLBACK("PerlAuthzHandler",
+                  PERL_REQ_DIR_HANDLER(cfg, cld, PerlAuthzHandler));
     return status;
 }
 #endif
@@ -1029,7 +1047,9 @@
 {
     dSTATUS;
     dPPDIR;
-    PERL_CALLBACK("PerlAccessHandler", cld->PerlAccessHandler);
+    dPPREQ;
+    PERL_CALLBACK("PerlAccessHandler",
+                  PERL_REQ_DIR_HANDLER(cfg, cld, PerlAccessHandler));
     return status;
 }
 #endif
@@ -1039,7 +1059,9 @@
 {
     dSTATUS;
     dPPDIR;
-    PERL_CALLBACK("PerlTypeHandler", cld->PerlTypeHandler);
+    dPPREQ;
+    PERL_CALLBACK("PerlTypeHandler",
+                  PERL_REQ_DIR_HANDLER(cfg, cld, PerlTypeHandler));
     return status;
 }
 #endif
@@ -1049,7 +1071,9 @@
 {
     dSTATUS;
     dPPDIR;
-    PERL_CALLBACK("PerlFixupHandler", cld->PerlFixupHandler);
+    dPPREQ;
+    PERL_CALLBACK("PerlFixupHandler",
+                  PERL_REQ_DIR_HANDLER(cfg, cld, PerlFixupHandler));
     return status;
 }
 #endif
@@ -1059,7 +1083,9 @@
 {
     dSTATUS;
     dPPDIR;
-    PERL_CALLBACK("PerlLogHandler", cld->PerlLogHandler);
+    dPPREQ;
+    PERL_CALLBACK("PerlLogHandler",
+                  PERL_REQ_DIR_HANDLER(cfg, cld, PerlLogHandler));
     return status;
 }
 #endif
@@ -1117,9 +1143,11 @@
     request_rec *r = (request_rec *)data;
     dSTATUS;
     dPPDIR;
+    dPPREQ;
 
 #ifdef PERL_CLEANUP
-    PERL_CALLBACK("PerlCleanupHandler", CleanupHandler);
+    PERL_CALLBACK("PerlCleanupHandler",
+                  PERL_REQ_DIR_HANDLER(cfg, cld, PerlCleanupHandler));
 #endif
 
     MP_TRACE_g(fprintf(stderr, "perl_end_cleanup..."));
Index: src/modules/perl/mod_perl.h
===================================================================
RCS file: /home/cvs/modperl/src/modules/perl/mod_perl.h,v
retrieving revision 1.102
diff -u -r1.102 mod_perl.h
--- src/modules/perl/mod_perl.h	2000/08/15 19:36:33	1.102
+++ src/modules/perl/mod_perl.h	2000/08/16 00:46:46
@@ -1058,7 +1058,15 @@
     HV *pnotes;
     int setup_env;
     array_header *sigsave;
+    perl_dir_config *dir_cfg;
+    perl_server_config *srv_cfg;
 } perl_request_config;
+
+#define PERL_REQ_DIR_HANDLER(cfg, cld, h) \
+((cfg && cfg->dir_cfg && cfg->dir_cfg->h) ? cfg->dir_cfg->h : cld->h)
+
+#define PERL_REQ_SRV_HANDLER(cfg, cls, h) \
+((cfg && cfg->srv_cfg && cfg->srv_cfg->h) ? cfg->srv_cfg->h : cls->h)
 
 typedef struct {
     int is_method;