Doug,
I didn't see in the announcement that the below fix is included in
1.25_01. Can you please confirm?
Regards,
Christian
> -----Original Message-----
> From: Doug MacEachern [mailto:[EMAIL PROTECTED]]
> Sent: Tuesday, August 15, 2000 7:59 PM
> To: [EMAIL PROTECTED]
> Cc: 'Modperl Mailing List (E-mail)'
> Subject: 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;
>