On Tuesday, 27 March 2012 12:48:01 Charlie Katz wrote:
> Still, can someone explain why
> 
>    PerlSetEnv  ENV_VAR /my/value
> 
> has different effects than
> 
>    <Perl>
>    $ENV{ENV_VAR} = '/my/value';
>    </Perl>
> 
> ?

The source of the problem is that apache 2 is in general multithreaded. Thus, 
one request may set $ENV{var}=1 while the other may $ENV{var}=2 at the same 
time. The environment is a process global variable.

To deal with the problem apache invented $r->subprocess_env, a table similar 
to the process environment but request specific. Then if there is a need to 
spawn off a new process and it is done via the apache API that table is copied 
to the process environment in the child process. For mod_cgi that solves the 
problem.

Perl itself adds another layer to the problem because at least some versions 
do not serialize access to the environment. So in principle it may even cause 
segfaults if 2 threads are trying to modify %ENV at the same time.

When modperl was ported to apache 2 it was decided to map %ENV to
$r->subprocess_env to prevent trouble.

So, with the current implementation, if there is a current request %ENV maps 
to its subprocess_env table. Otherwise Perl's original functions are called 
and thus modify the process global environment, see modperl_env.c

If you modify %ENV in a <Perl> block there is obviously no request since the 
code is executed at server startup. PerlSetEnv on the other hand is executed 
as soon as possible in the request cycle. At that time there is a current 
request and hence $r->subprocess_env is modified.

There is another way to modify the environment, SetEnv. The difference between 
PerlSetEnv and SetEnv is the point within the request cycle when it is 
executed. As said before PerlSetEnv is done first thing. Apache's SetEnv is 
there to set environment variables for CGI scripts and other normal handlers. 
For those it is sufficient to populate subprocess_env just before the response 
handler is called. So, SetEnv lives in the fixup phase.

Since I am not the author of the code I don't know for sure all of the above. 
But I think over time I have got quite a bit of understanding of the problem 
from reading the code. Of course, one could ask what happens in a 
multithreaded MPM when 2 PerlProcessConnectionHandlers simultaneously try to 
modify %ENV. I don't know. Maybe it segfaults since there is no $r in this 
situation.

Would be good if someone could at least setup a test scenario for this case.

Torsten Förtsch

-- 
Need professional modperl support? Hire me! (http://foertsch.name)

Like fantasy? http://kabatinte.net

Reply via email to