On Sunday, 16 October 2011 02:26:53 Ævar Arnfjörð Bjarmason wrote: > > $ cat xx > > <Perl> > > use POSIX(); > > POSIX::exit(15); > > </Perl> > > $ httpd -c 'Include "'$PWD/xx'"'; echo $? > > 15 > > $ cat xx > > <Perl> > > die > > </Perl> > > $ httpd -c 'Include "'$PWD/xx'"'; echo $? > > Syntax error on line 2 of /.../xx: > > \t(in cleanup) Died at /.../xx line 2.\n > > 1 > > $ > > I can load code earlier, but unless I'm misunderstanding something the > PerlInterpreter running that code won't be the one that'll be forked > and serving requests.
If you are running prefork with a non-threaded perl (-Uuseithreads and -Uusemultiplicity) it's always the same interpreter. The only thing is the code in a <Perl> block is interpreted twice at startup. Between the both runs the interpreter shuts down. If modperl is compiled as shared library it is even unloaded from memory. The same happens by the way when Apache receives a SIGHUP (restart) or SIGUSR1 (graceful restart). Now let's see what happens with a threaded perl and worker MPM. Here is again my xx file that is included after the main httpd.conf has been read. 0 r2@opi ~/Download$ cat xx <Perl> package XX; use ModPerl::Util (); use Apache2::RequestRec (); use Apache2::RequestIO (); use Apache2::ServerUtil (); sub stderr {readlink "/proc/$$/fd/2"} sub l { open my $f, '>>', '/tmp/xx'; print $f "$$: ".ModPerl::Util::current_callback. ": perl=".ModPerl::Util::current_perl_id. " restart_count=".Apache2::ServerUtil::restart_count. " stderr=".stderr."\n"; 0; } l; sub handler { my ($r)=@_; $r->content_type("text/plain"); $r->print("$$: perl=".ModPerl::Util::current_perl_id. " restart_count=".Apache2::ServerUtil::restart_count."\n"); 0; } </Perl> <Location /xx> SetHandler modperl PerlResponseHandler XX </Location> PerlChildInitHandler XX::l PerlPostConfigHandler XX::l PerlFixupHandler XX::l 0 r2@opi ~/Download$ :>/tmp/xx && > chmod 666 /tmp/xx && > sudo /opt/apache-worker/sbin/httpd -f > /etc/opt/apache-worker/original/httpd-modperl.conf -c 'Include "'$PWD/xx\" 0 r2@opi ~/Download$ cat /tmp/xx 19751: ��z: perl=0x79f3f0 restart_count=1 stderr=/dev/pts/4 19751: PerlPostConfigHandler: perl=0x79f3f0 restart_count=1 stderr=/var/opt/apache-worker/logs/error_log PID 19751 is the parent of the process that is normally referred to as the parent apache. This process is still a child of the shell and hence can report a return code. In the first line STDERR is still connected to the terminal. PostConfig runs after OpenLogs. So, here error_log is active and STDERR goes there. Now apache throws away all done so far and even unloads modperl from memory. Also STDERR is closed and the httpd disconnects from the calling shell. 19752: �>l: perl=0x9932b0 restart_count=2 stderr=/dev/null 19752: PerlPostConfigHandler: perl=0x9932b0 restart_count=2 stderr=/var/opt/apache-worker/logs/error_log PPID of process 19752 is 1. Now httpd cannot report to the shell. The perl interpreter 0x9932b0 is called the interpreter pool parent. Later on when requests are served this interpreter is cloned. So, the clones inherit all the code that is compiled in this interpreter. An exception to this rule is the PerlOption +Parent. If a VHost is configured with this option it gets a brand new interpreter pool parent. 19754: PerlChildInitHandler: perl=0x9932b0 restart_count=2 stderr=/var/opt/apache-worker/logs/error_log 19755: PerlChildInitHandler: perl=0x9932b0 restart_count=2 stderr=/var/opt/apache-worker/logs/error_log 19756: PerlChildInitHandler: perl=0x9932b0 restart_count=2 stderr=/var/opt/apache-worker/logs/error_log The same interpreter runs the ChildInit phase for each child process. Now let's see what happens at runtime: 0 r2@opi ~/Download$ curl http://localhost/xx 19754: perl=0xb7a2d0 restart_count=2 Perl interpreter 0xb7a2d0 is a clone of 0x9932b0. It is created on demand. But the fact that is can execute the code from the <Perl> section shows that it inherits such things. 0 r2@opi ~/Download$ tail -2 /tmp/xx 19756: PerlChildInitHandler: perl=0x9932b0 restart_count=2 stderr=/var/opt/apache-worker/logs/error_log 19754: PerlFixupHandler: perl=0xb7a2d0 restart_count=2 stderr= The Fixup handler is run by the same interpreter. This can be controlled by the PerlInterpScope directive which is "request" by default. Were it "handler" we couldn't say for sure that the Response phase is run by the same interpreter as Fixup is. But both interpreters would be clones of the interpreter pool parent. Conclusion: 1) As can be seen by the example above httpd can report a return code to the calling shell only while restart_count==1. Otherwise it has already disconnected and is a child of the init process. 2) Application code can be compiled in <Perl> sections, by PerlLoadModule or PerlConfigRequire. It is inherited by the interpreter cloning process. The important point for you is 1). httpd will report the status code to the calling shell also if the interpreter is started by a PerlRequire or PerlPostConfigRequire but only if restart_count is still 1. Torsten Förtsch -- Need professional modperl support? Hire me! (http://foertsch.name) Like fantasy? http://kabatinte.net