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