perl-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Stas Bekman <s...@stason.org>
Subject Re: [mp2 bug] Perl*Env issues
Date Thu, 16 Dec 2004 21:17:25 GMT
Larry Leszczynski wrote:
> Hi Stas -
> 
> 
>>I propose the following "simple" solution:
>>
>>1) Keep %ENV intact at the server startup, so anything set in the shell is
>>seen from perl
>>2) PerlPassEnv and PerlSetEnv aren't run yet but postponed to until after
>>post_config.
>>3) just before starting workers, detach %ENV from environ, cleaning it up
>>completely. now run PerlPassEnv and PerlSetEnv from (2)
>>
>>That way we don't have to deal with the painful timing of PerlPassEnv and
>>PerlSetEnv. We simply document that those have an affect *only*
>>post-post_config phase, i.e. starting from child_init phase. If someone
>>wants to modify %ENV as it's seen from shell, they can just do that with
>><Perl> sections.
> 
> 
> I like it a lot, it should be easy for people to understand the flow.
> 
> Just want to make sure I understand something:  I think in #3 above when
> you say "cleaning it up completely", you mean cleaning up environ
> completely (so workers don't inherit) but keeping %ENV available for
> PerlPassEnv, right?  So I should be able to do something like this:
> 
>    (assume shell env has PATH and INSTANCE variables set)
> 
>    <Perl>
>       $ENV{PATH} = $ENV{INSTANCE} eq 'development'
>                    ? "$ENV{PATH}:/extra/devl/path/needed/by/my/modules"
>                    : "$ENV{PATH}:/extra/prod/path/needed/by/my/modules";
>    </Perl>
> 
>    PerlPassEnv PATH
> 
>    (now worker %ENV contains modified PATH, but not INSTANCE)
> 
> 
> Yes?

Yes. Good thinking, Larry.

In fact this will do exactly the same:

    PerlPassEnv PATH
    <Perl>
       $ENV{PATH} = $ENV{INSTANCE} eq 'development'
                    ? "$ENV{PATH}:/extra/devl/path/needed/by/my/modules"
                    : "$ENV{PATH}:/extra/prod/path/needed/by/my/modules";
    </Perl>

It will just keep the latest %ENV value, if you ever called: PerlPassEnv 
or PerlSetEnv.

There is one tricky issue though. There is only one %ENV, so a vhost with 
its own interpreter changing %ENV will affect the base server too. So may 
be a better solution is this:

1) copy environ to %ENV and detach at the very beginning.

now if a vhost with its own interpreter changes %ENV it won't affect the 
base server.

2) when the post_config phases ends we clear all %ENV fields, which 
weren't mentioned in PerlPassEnv or PerlSetEnv.

But, that will mean that if you set $ENV{MYFOO} at startup it won't stay 
around, unless you explicitly asked to post it forward. What I don't like 
about it is that $ENV{PATH} is set in the perl code (e.g. startup), but 
needs to be marked in httpd.conf, that's ugly.

How about this solution:

1) at the beginning make a copy of the keys of original environ, which is 
maintained as a delete list:

   delete_list: HOME USER SHELL PATH
        %ENV{qw(HOME USER SHELL PATH);

2) if any of the existing keys is modified, let's say PATH, it gets 
removed from the delete list, so:

   $ENV{PATH} = "/tmp";

results in:

   delete_list: HOME USER SHELL
        %ENV{qw(HOME USER SHELL PATH);

3) if PerlPassEnv is called, the delete_list is adjusted to remove that 
key. So if:

   PerlPassEnv USER

is called we now have:

   delete_list: HOME      SHELL
        %ENV{qw(HOME USER SHELL PATH);

4) if a new key/value pair is added (or deleted) w/o localizing %ENV (via 
perl code or PerlSetEnv), it's added to %ENV, e.g. if:

   PerlSetEnv FOO 1
   <Perl> $ENV{BAR}

results in:

   delete_list: HOME      SHELL
        %ENV{qw(HOME USER SHELL PATH FOO BAR);

5) finally after the post_config phase and before child_init phase, we 
cleanup %ENV using the delete_list, which leaves us with:

   delete_list:
        %ENV{qw(USER PATH FOO BAR);

How does that sound?

The only remaining problem that I see is PerlSetEnv, if there is a 
PerlRequire'd file and PerlSetEnv, and both try to set/modify the same 
entry, it's not the order in httpd.conf that will determine which is the 
latest value, but the order of evalution of PerlRequire vs. PerlSetEnv.

Another thing to ensure is that PerlSetEnv is run before PerlRequire, 
since it's possible that the file will want to refer to the ENV var set by
PerlSetEnv.

Oh boy, I'm sure you can find lots of holes in this proposal :( That's a 
tricky business.

-- 
__________________________________________________________________
Stas Bekman            JAm_pH ------> Just Another mod_perl Hacker
http://stason.org/     mod_perl Guide ---> http://perl.apache.org
mailto:stas@stason.org http://use.perl.org http://apacheweek.com
http://modperlbook.org http://apache.org   http://ticketmaster.com

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@perl.apache.org
For additional commands, e-mail: dev-help@perl.apache.org


Mime
View raw message