Thanks for the detailed explanation.  I guess the explanation for the
behavior I see is that the C library called through Perl only has access to
the process global %ENV, and not to the particular $r->subprocess_env data
for the request through which it was called.

On Tue, Mar 27, 2012 at 1:53 PM, Torsten Förtsch
<torsten.foert...@gmx.net>wrote:

> 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