dougm       01/11/14 19:02:43

  Modified:    src/modules/perl mod_perl.c modperl_env.c modperl_env.h
               t/conf   modperl_extra.pl
               t/modperl .cvsignore
  Log:
  more complete implementation of tie %ENV to r->subprocess_env
  
  Revision  Changes    Path
  1.95      +2 -7      modperl-2.0/src/modules/perl/mod_perl.c
  
  Index: mod_perl.c
  ===================================================================
  RCS file: /home/cvs/modperl-2.0/src/modules/perl/mod_perl.c,v
  retrieving revision 1.94
  retrieving revision 1.95
  diff -u -r1.94 -r1.95
  --- mod_perl.c        2001/11/15 01:30:45     1.94
  +++ mod_perl.c        2001/11/15 03:02:42     1.95
  @@ -147,6 +147,8 @@
           return;
       }
   
  +    modperl_env_init();
  +
       base_perl = modperl_startup(base_server, p);
   
   #ifdef USE_ITHREADS
  @@ -538,21 +540,14 @@
       h_stdout = modperl_io_tie_stdout(aTHX_ r);
       h_stdin  = modperl_io_tie_stdin(aTHX_ r);
   
  -#if 0
  -    /* current implementation of tie %ENV to $r->subprocess_env 
  -     * is not threadsafe
  -     */
       modperl_env_request_tie(aTHX_ r);
  -#endif
   
       retval = modperl_response_handler_run(r, FALSE);
   
       modperl_io_handle_untie(aTHX_ h_stdout);
       modperl_io_handle_untie(aTHX_ h_stdin);
   
  -#if 0
       modperl_env_request_untie(aTHX_ r);
  -#endif
   
       modperl_perl_global_request_restore(aTHX_ r);
   
  
  
  
  1.19      +150 -41   modperl-2.0/src/modules/perl/modperl_env.c
  
  Index: modperl_env.c
  ===================================================================
  RCS file: /home/cvs/modperl-2.0/src/modules/perl/modperl_env.c,v
  retrieving revision 1.18
  retrieving revision 1.19
  diff -u -r1.18 -r1.19
  --- modperl_env.c     2001/11/12 22:14:36     1.18
  +++ modperl_env.c     2001/11/15 03:02:43     1.19
  @@ -1,6 +1,7 @@
   #include "mod_perl.h"
   
   #define EnvMgObj SvMAGIC((SV*)ENVHV)->mg_ptr
  +#define EnvMgLen SvMAGIC((SV*)ENVHV)->mg_len
   
   static MP_INLINE
   void modperl_env_hv_store(pTHX_ HV *hv, apr_table_entry_t *elt)
  @@ -87,7 +88,6 @@
       const apr_array_header_t *array;
       apr_table_entry_t *elts;
   
  -
       if (MpReqSETUP_ENV(rcfg)) {
           return;
       }
  @@ -118,69 +118,178 @@
       MpReqSETUP_ENV_On(rcfg);
   }
   
  -static int modperl_env_request_set(pTHX_ SV *sv, MAGIC *mg)
  +void modperl_env_request_tie(pTHX_ request_rec *r)
   {
  -    const char *key, *val;
  -    STRLEN klen, vlen;
  -    request_rec *r = (request_rec *)EnvMgObj;
  +    EnvMgObj = (char *)r;
  +    EnvMgLen = -1;
  +
  +#ifdef MP_PERL_HV_GMAGICAL_AWARE
  +    SvGMAGICAL_on((SV*)ENVHV);
  +#endif
  +}
  +
  +void modperl_env_request_untie(pTHX_ request_rec *r)
  +{
  +    EnvMgObj = NULL;
  +
  +#ifdef MP_PERL_HV_GMAGICAL_AWARE
  +    SvGMAGICAL_off((SV*)ENVHV);
  +#endif
  +}
  +
  +/* to store the original virtual tables
  + * these are global, not per-interpreter
  + */
  +static MGVTBL MP_PERL_vtbl_env;
  +static MGVTBL MP_PERL_vtbl_envelem;
   
  -    key = (const char *)MgPV(mg,klen);
  -    val = (const char *)SvPV(sv,vlen);
  +#define MP_PL_vtbl_call(name, meth) \
  +    MP_PERL_vtbl_##name.svt_##meth(aTHX_ sv, mg)
   
  -    apr_table_set(r->subprocess_env, key, val);
  +#define MP_dENV_KEY \
  +    STRLEN klen; \
  +    const char *key = (const char *)MgPV(mg,klen)
  +
  +#define MP_dENV_VAL \
  +    STRLEN vlen; \
  +    const char *val = (const char *)SvPV(sv,vlen)
   
  -    /*return magic_setenv(sv, mg);*/
  +/*
  + * XXX: what we do here might change:
  + *      - make it optional for %ENV to be tied to r->subprocess_env
  + *      - make it possible to modify environ
  + *      - we could allow modification of environ if mpm isn't threaded
  + *      - we could allow modification of environ if variable isn't a CGI
  + *        variable (still could cause problems)
  + */
  +/*
  + * problems we are trying to solve:
  + *      - environ is shared between threads
  + *          + Perl does not serialize access to environ
  + *          + even if it did, CGI variables cannot be shared between threads!
  + * problems we create by trying to solve above problems:
  + *      - a forked process will not inherit the current %ENV
  + *      - C libraries might rely on environ, e.g. DBD::Oracle
  + */
  +static int modperl_env_magic_set_all(pTHX_ SV *sv, MAGIC *mg)
  +{
  +    request_rec *r = (request_rec *)EnvMgObj;
   
  +    if (r) {
  +        if (PL_localizing) {
  +            /* local %ENV = (FOO => 'bar', BIZ => 'baz') */
  +            HE *entry;
  +            STRLEN n_a;
  +
  +            hv_iterinit((HV*)sv);
  +            while ((entry = hv_iternext((HV*)sv))) {
  +                I32 keylen;
  +                apr_table_set(r->subprocess_env,
  +                              hv_iterkey(entry, &keylen),
  +                              SvPV(hv_iterval((HV*)sv, entry), n_a));
  +            }
  +        }
  +    }
  +    else {
  +        return MP_PL_vtbl_call(env, set);
  +    }
  +
       return 0;
   }
   
  -#ifdef MP_PERL_HV_GMAGICAL_AWARE
  -static int modperl_env_request_get(pTHX_ SV *sv, MAGIC *mg)
  +static int modperl_env_magic_clear_all(pTHX_ SV *sv, MAGIC *mg)
   {
  -    const char *key, *val;
  -    STRLEN klen;
       request_rec *r = (request_rec *)EnvMgObj;
  -
  -    key = (const char *)MgPV(mg,klen);
   
  -    if ((val = apr_table_get(r->subprocess_env, key))) {
  -        sv_setpv(sv, val);
  +    if (r) {
  +        apr_table_clear(r->subprocess_env);
       }
       else {
  -        sv_setsv(sv, &PL_sv_undef);
  +        return MP_PL_vtbl_call(env, clear);
       }
   
       return 0;
   }
  -#endif
   
  -/*
  - * XXX: PL_vtbl_* are global (not per-interpreter)
  - * so this method of tie-ing is not thread-safe
  - * overridding svt_get is only useful with 5.7.2+ and requires
  - * a smarter lookup than the current modperl_env_request_get
  - */
  -void modperl_env_request_tie(pTHX_ request_rec *r)
  +static int modperl_env_magic_set(pTHX_ SV *sv, MAGIC *mg)
   {
  -    EnvMgObj = (char *)r;
  +    request_rec *r = (request_rec *)EnvMgObj;
   
  -    PL_vtbl_envelem.svt_set = MEMBER_TO_FPTR(modperl_env_request_set);
  -#ifdef MP_PERL_HV_GMAGICAL_AWARE
  -    SvGMAGICAL_on((SV*)ENVHV);
  -    PL_vtbl_envelem.svt_get = MEMBER_TO_FPTR(modperl_env_request_get);
  -#endif
  +    if (r) {
  +        MP_dENV_KEY;
  +        MP_dENV_VAL;
  +        apr_table_set(r->subprocess_env, key, val);
  +    }
  +    else {
  +        return MP_PL_vtbl_call(envelem, set);
  +    }
  +
  +    return 0;
   }
   
  -void modperl_env_request_untie(pTHX_ request_rec *r)
  +static int modperl_env_magic_clear(pTHX_ SV *sv, MAGIC *mg)
   {
  -#if 0
  -    /* XXX: not currently in use.  if enabled Perl_magic_setenv
  -     * is not available to win32
  -     */
  -    PL_vtbl_envelem.svt_set = MEMBER_TO_FPTR(Perl_magic_setenv);
  -#endif
  +    request_rec *r = (request_rec *)EnvMgObj;
  +
  +    if (r) {
  +        MP_dENV_KEY;
  +        apr_table_unset(r->subprocess_env, key);
  +    }
  +    else {
  +        return MP_PL_vtbl_call(envelem, clear);
  +    }
  +
  +    return 0;
  +}
  +
   #ifdef MP_PERL_HV_GMAGICAL_AWARE
  -    SvGMAGICAL_off((SV*)ENVHV);
  -    PL_vtbl_envelem.svt_get = 0;
  +static int modperl_env_magic_get(pTHX_ SV *sv, MAGIC *mg)
  +{
  +    request_rec *r = (request_rec *)EnvMgObj;
  +
  +    if (r) {
  +        MP_dENV_KEY;
  +        const char *val;
  +
  +        if ((val = apr_table_get(r->subprocess_env, key))) {
  +            sv_setpv(sv, val);
  +        }
  +        else {
  +            sv_setsv(sv, &PL_sv_undef);
  +        }
  +    }
  +    else {
  +        /* there is no svt_get in PL_vtbl_envelem */
  +    }
  +
  +    return 0;
  +}
   #endif
  +
  +/* override %ENV virtual tables with our own */
  +static MGVTBL MP_vtbl_env = {
  +    0,
  +    MEMBER_TO_FPTR(modperl_env_magic_set_all),
  +    0,
  +    MEMBER_TO_FPTR(modperl_env_magic_clear_all),
  +    0
  +};
  +
  +static MGVTBL MP_vtbl_envelem =      {
  +    0,
  +    MEMBER_TO_FPTR(modperl_env_magic_set),
  +    0,
  +    MEMBER_TO_FPTR(modperl_env_magic_clear),
  +    0
  +};
  +
  +void modperl_env_init(void)
  +{
  +    /* save originals */
  +    StructCopy(&PL_vtbl_env, &MP_PERL_vtbl_env, MGVTBL);
  +    StructCopy(&PL_vtbl_envelem, &MP_PERL_vtbl_envelem, MGVTBL);
  +
  +    /* replace with our versions */
  +    StructCopy(&MP_vtbl_env, &PL_vtbl_env, MGVTBL);
  +    StructCopy(&MP_vtbl_envelem, &PL_vtbl_envelem, MGVTBL);
   }
  
  
  
  1.10      +2 -0      modperl-2.0/src/modules/perl/modperl_env.h
  
  Index: modperl_env.h
  ===================================================================
  RCS file: /home/cvs/modperl-2.0/src/modules/perl/modperl_env.h,v
  retrieving revision 1.9
  retrieving revision 1.10
  diff -u -r1.9 -r1.10
  --- modperl_env.h     2001/10/13 19:11:32     1.9
  +++ modperl_env.h     2001/11/15 03:02:43     1.10
  @@ -23,4 +23,6 @@
   
   void modperl_env_request_untie(pTHX_ request_rec *r);
   
  +void modperl_env_init(void);
  +
   #endif /* MODPERL_ENV_H */
  
  
  
  1.10      +3 -0      modperl-2.0/t/conf/modperl_extra.pl
  
  Index: modperl_extra.pl
  ===================================================================
  RCS file: /home/cvs/modperl-2.0/t/conf/modperl_extra.pl,v
  retrieving revision 1.9
  retrieving revision 1.10
  diff -u -r1.9 -r1.10
  --- modperl_extra.pl  2001/10/09 18:01:21     1.9
  +++ modperl_extra.pl  2001/11/15 03:02:43     1.10
  @@ -18,6 +18,9 @@
       die '$ENV{MOD_PERL} not set!';
   }
   
  +#see t/response/TestModperl/env.pm
  +$ENV{MODPERL_EXTRA_PL} = __FILE__;
  +
   my $ap_mods = scalar grep { /^Apache/ } keys %INC;
   my $apr_mods = scalar grep { /^APR/ } keys %INC;
   
  
  
  
  1.7       +1 -0      modperl-2.0/t/modperl/.cvsignore
  
  Index: .cvsignore
  ===================================================================
  RCS file: /home/cvs/modperl-2.0/t/modperl/.cvsignore,v
  retrieving revision 1.6
  retrieving revision 1.7
  diff -u -r1.6 -r1.7
  --- .cvsignore        2001/11/13 18:35:08     1.6
  +++ .cvsignore        2001/11/15 03:02:43     1.7
  @@ -1,3 +1,4 @@
  +env.t
   endav.t
   exit.t
   printf.t
  
  
  


Reply via email to