Index: src/modules/perl/Apache.xs =================================================================== RCS file: /home/cvs/modperl/src/modules/perl/Apache.xs,v retrieving revision 1.107 diff -u -r1.107 Apache.xs --- src/modules/perl/Apache.xs 2000/08/31 20:54:23 1.107 +++ src/modules/perl/Apache.xs 2000/09/01 18:58:11 @@ -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); @@ -105,25 +99,13 @@ { 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; @@ -134,45 +116,57 @@ } } +#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"); + } + + /* since register_cleanups are fifo, and the already registered + * mod_perl_end_cleanup() runs PerlCleanupHandlers, PerlCleanupHandler + * needs to maintain the refcnt itself + */ + if (do_register_cleanup && strNE(tab->name, "PerlCleanupHandler")) { + 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) @@ -186,29 +180,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.126 diff -u -r1.126 mod_perl.c --- src/modules/perl/mod_perl.c 2000/09/01 05:23:17 1.126 +++ src/modules/perl/mod_perl.c 2000/09/01 18:58:11 @@ -322,7 +322,7 @@ dSTATUS; dPSRV(s); request_rec *r = mp_fake_request_rec(s, p, hook); - PERL_CALLBACK(hook, cls->PerlRestartHandler); + PERL_CALLBACK(hook, cls->PerlRestartHandler, 0, NULL); } #endif @@ -902,7 +902,8 @@ } cfg->setup_env = 1; - PERL_CALLBACK("PerlHandler", cld->PerlHandler); + PERL_CALLBACK_DIR("PerlHandler", PerlHandler); + cfg->setup_env = 0; FREETMPS; @@ -942,7 +943,7 @@ mod_perl_init_ids(); Apache__ServerStarting(FALSE); - PERL_CALLBACK(hook, cls->PerlChildInitHandler); + PERL_CALLBACK(hook, cls->PerlChildInitHandler, 0, NULL); } #endif @@ -954,7 +955,7 @@ dPSRV(s); request_rec *r = mp_fake_request_rec(s, p, hook); - PERL_CALLBACK(hook, cls->PerlChildExitHandler); + PERL_CALLBACK(hook, cls->PerlChildExitHandler, 0, NULL); perl_shutdown(s,p); } @@ -976,16 +977,19 @@ { dSTATUS; dPSRV(r->server); + #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_SRV("PerlInitHandler", PerlInitHandler); #endif - PERL_CALLBACK("PerlPostReadRequestHandler", cls->PerlPostReadRequestHandler); + PERL_CALLBACK_SRV("PerlPostReadRequestHandler", + PerlPostReadRequestHandler); return status; } #endif @@ -995,7 +999,7 @@ { dSTATUS; dPSRV(r->server); - PERL_CALLBACK("PerlTransHandler", cls->PerlTransHandler); + PERL_CALLBACK_SRV("PerlTransHandler", PerlTransHandler); return status; } #endif @@ -1006,11 +1010,9 @@ dSTATUS; dPPDIR; #ifdef PERL_INIT - PERL_CALLBACK("PerlInitHandler", - cld->PerlInitHandler); + PERL_CALLBACK_DIR("PerlInitHandler", PerlInitHandler); #endif - PERL_CALLBACK("PerlHeaderParserHandler", - cld->PerlHeaderParserHandler); + PERL_CALLBACK_DIR("PerlHeaderParserHandler", PerlHeaderParserHandler); return status; } #endif @@ -1020,7 +1022,7 @@ { dSTATUS; dPPDIR; - PERL_CALLBACK("PerlAuthenHandler", cld->PerlAuthenHandler); + PERL_CALLBACK_DIR("PerlAuthenHandler", PerlAuthenHandler); return status; } #endif @@ -1030,7 +1032,7 @@ { dSTATUS; dPPDIR; - PERL_CALLBACK("PerlAuthzHandler", cld->PerlAuthzHandler); + PERL_CALLBACK_DIR("PerlAuthzHandler", PerlAuthzHandler); return status; } #endif @@ -1040,7 +1042,7 @@ { dSTATUS; dPPDIR; - PERL_CALLBACK("PerlAccessHandler", cld->PerlAccessHandler); + PERL_CALLBACK_DIR("PerlAccessHandler", PerlAccessHandler); return status; } #endif @@ -1050,7 +1052,7 @@ { dSTATUS; dPPDIR; - PERL_CALLBACK("PerlTypeHandler", cld->PerlTypeHandler); + PERL_CALLBACK_DIR("PerlTypeHandler", PerlTypeHandler); return status; } #endif @@ -1060,7 +1062,7 @@ { dSTATUS; dPPDIR; - PERL_CALLBACK("PerlFixupHandler", cld->PerlFixupHandler); + PERL_CALLBACK_DIR("PerlFixupHandler", PerlFixupHandler); return status; } #endif @@ -1070,7 +1072,7 @@ { dSTATUS; dPPDIR; - PERL_CALLBACK("PerlLogHandler", cld->PerlLogHandler); + PERL_CALLBACK_DIR("PerlLogHandler", PerlLogHandler); return status; } #endif @@ -1128,9 +1130,13 @@ request_rec *r = (request_rec *)data; dSTATUS; dPPDIR; + dPPREQ; #ifdef PERL_CLEANUP - PERL_CALLBACK("PerlCleanupHandler", CleanupHandler); + PERL_CALLBACK_DIR("PerlCleanupHandler", PerlCleanupHandler); + if (PERL_HAS_REQ_DIR_HANDLER(cfg, PerlCleanupHandler)) { + SvREFCNT_dec((SV*)cfg->dir_cfg->PerlCleanupHandler); + } #endif MP_TRACE_g(fprintf(stderr, "perl_end_cleanup...")); @@ -1304,12 +1310,23 @@ return 0; } -int perl_run_stacked_handlers(char *hook, request_rec *r, AV *handlers) +#define cfg_ptr_get \ +(cfg_type == 1 ? (void *)cfg->srv_cfg : (void *)cfg->dir_cfg) + +#define set_handlers_get \ +(AV**)(((char *)cfg_ptr)+offset) + +int perl_run_stacked_handlers(char *hook, request_rec *r, + AV *handlers, int cfg_type, void *offset_ptr) { dSTATUS; - I32 i, do_clear=FALSE; + I32 i, fill, do_clear=FALSE; SV *sub, **svp; int hook_len = strlen(hook); + perl_request_config *cfg = NULL; + void *cfg_ptr = NULL; + AV **set_handlers = NULL; + int offset = (int)(long)offset_ptr; #ifdef USE_ITHREADS dTHX; @@ -1319,6 +1336,19 @@ } #endif + if (offset_ptr && r->request_config) { + cfg = (perl_request_config *) + get_module_config(r->request_config, &perl_module); + if (cfg && (cfg_ptr = cfg_ptr_get)) { + if ((set_handlers = set_handlers_get) && *set_handlers) { + handlers = *set_handlers; + } + } + if (!handlers) { + return DECLINED; + } + } + if(handlers == Nullav) { if(hv_exists(stacked_handlers, hook, hook_len)) { svp = hv_fetch(stacked_handlers, hook, hook_len, 0); @@ -1353,7 +1383,10 @@ "running %d server configured stacked handlers for %s...\n", (int)AvFILL(handlers)+1, r->uri)); } - for(i=0; i<=AvFILL(handlers); i++) { + + run_handlers: + fill = AvFILL(handlers); + for (i=0; i<=AvFILL(handlers); i++) { MP_TRACE_h(fprintf(stderr, "calling &{%s->[%d]} (%d total)\n", hook, (int)i, (int)AvFILL(handlers)+1)); @@ -1376,6 +1409,14 @@ av_clear(handlers); return status; } + if (cfg && (cfg_ptr = cfg_ptr_get)) { + if ((set_handlers = set_handlers_get) && *set_handlers) { + if (AvFILL(*set_handlers) != fill) { + handlers = *set_handlers; + goto run_handlers; + } + } + } } } if(do_clear) 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/09/01 18:58:11 @@ -691,23 +691,31 @@ #define NO_HANDLERS -666 -#define PERL_CALLBACK(h,name) \ +#define PERL_CALLBACK(h,name,cfg_type,offset) \ PERL_SET_CUR_HOOK(h); \ (void)acquire_mutex(mod_perl_mutex); \ -if(AvTRUE(name)) { \ - status = perl_run_stacked_handlers(h, r, name); \ +if (AvTRUE(name) || cfg_type) { \ + status = perl_run_stacked_handlers(h, r, name, cfg_type, offset); \ } \ if((status != OK) && (status != DECLINED)) { \ MP_TRACE_h(fprintf(stderr, "%s handlers returned %d\n", h, status)); \ } \ else { \ - dstatus = perl_run_stacked_handlers(h, r, Nullav); \ + dstatus = perl_run_stacked_handlers(h, r, Nullav, 0, NULL); \ if(dstatus != NO_HANDLERS) status = dstatus; \ } \ (void)release_mutex(mod_perl_mutex); \ MP_TRACE_h(fprintf(stderr, "%s handlers returned %d\n", h, status)) - +#define PERL_CALLBACK_DIR(phase, handler) \ +PERL_CALLBACK(phase, cld->handler, \ + 2, \ + PERL_REQ_DIR_HANDLER_OFFSET(handler)) + +#define PERL_CALLBACK_SRV(phase, handler) \ +PERL_CALLBACK(phase, cls->handler, \ + 1, \ + PERL_REQ_SRV_HANDLER_OFFSET(handler)) #else #define PERL_TAKE TAKE1 @@ -716,7 +724,7 @@ #define mod_perl_can_stack_handlers(sv) (SvTRUE(sv) && 0) -#define PERL_CALLBACK(h,name) \ +#define PERL_CALLBACK(h,name,dummy) \ PERL_SET_CUR_HOOK(h); \ if(name != NULL) { \ SV *sv; \ @@ -1058,8 +1066,22 @@ HV *pnotes; int setup_env; array_header *sigsave; + perl_dir_config *dir_cfg; + perl_server_config *srv_cfg; } perl_request_config; +#define PERL_HAS_REQ_DIR_HANDLER(cfg, h) \ +(cfg && cfg->dir_cfg && cfg->dir_cfg->h) + +#define PERL_HAS_REQ_SRV_HANDLER(cfg, h) \ +(cfg && cfg->srv_cfg && cfg->srv_cfg->h) + +#define PERL_REQ_DIR_HANDLER_OFFSET(h) \ +(void*)XtOffsetOf(perl_dir_config, h) + +#define PERL_REQ_SRV_HANDLER_OFFSET(h) \ +(void*)XtOffsetOf(perl_server_config, h) + typedef struct { int is_method; int is_anon; @@ -1105,7 +1127,8 @@ SV *mod_perl_pop_handlers(SV *self, SV *hook); void *mod_perl_clear_handlers(SV *self, SV *hook); SV *mod_perl_fetch_handlers(SV *self, SV *hook); -int perl_run_stacked_handlers(char *hook, request_rec *r, AV *handlers); +int perl_run_stacked_handlers(char *hook, request_rec *r, + AV *handlers, int cfg_type, void *offset); /* plugin slots */ void perl_module_init(server_rec *s, pool *p);