I've had a rather annoying problem with Apache::Registry incorrectly
caching documents.  I'll attempt to explain the behavior I'm seeing and
why I consider this to be a bug (this gets pretty techie, be warned)...

I've found that the first time any given instance of an httpd processes
a mod_perl script, it gets compiled into a unique package name based off
the server name and the URI to the file.  For example, if your URL was
http://test.xyz.com/test.mpl (I like to use .mpl for all my mod_perl
scripts), the resulting package name would be

Apache::ROOTtest_2exyz_2ecom::test_2empl

which is just fine and dandy.  But the second time any Apache::Registry
script is run, the hostname part of the package is remove, and a new
script gets compiled into

Apache::ROOT::test_2empl

Which totally BREAKS the script if does a require(), the problem being
that once the require() is done, %INC has been modified for that process
to prevent the file from being processed again, and you LOSE the ability
to call any functions or variables that were essentially assigned in the
original invocation's namespace (assuming the require'd file doesn't
start a new package), but are no longer available because the package
name is different the second time around.  (That was a mouthful.)

So what I'm saying is that if the first time test.mpl is run on a
totally fresh httpd, and a file with some function definitions is
required, the definitions are lost on the second time that script is run
in the same daemon because it's running in a different package with a
different namespace.

After a few hours of tracing around in Apache::Registry, I've found that
somehow $Apache::Registry::NameWithVirtualHost is being set to some
non-true value after the first script which causes the code that
generates the name of the package to not include the hostname in the
package.  The code is specifically this:

        if($Apache::Registry::NameWithVirtualHost) {
            my $name = $r->get_server_name;
            $script_name = join "", $name, $script_name if $name;
        }

If I comment out the if conditional and the closing block lines,
everything works fine, and the full package name with hostname is
generated each time.  This may just be a workaround to some greater
problem (who the heck knows why NameWithVirtualHost is being set
non-true?!), but it was a really annoying problem to track down and deal
with.  And I'm not quite sure why this particular flag exists -- it's
not documented, and you'd have to set it inside your httpd's conf file
with a <Perl> section to have it make any difference (unless all your
virtual host names were actually the same logical server, in which case
you'd just be wasting cache space by compiling each script into a new
namespace for no real effect).

If anyone has any guesses as to why that value is being set false or if
there is a bigger problem at hand, I'd love to hear it.  Otherwise, I
submit this as a bug in the Apache::Registry module.

Incidentally, I think Apache::PerlRun has this problem too, and it
actually uses the $Apache::Registry::NameWithVirtalHost value instead of
one in its own package.  Bug or feature?  You decide!  :-)

Doug

Reply via email to