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 > > >