On Tue, May 23, 2000 at 07:15:46AM -0500, Ken Williams <[EMAIL PROTECTED]> 
wrote:
> >my $global = 5;
> >sub set_global {
> >   $global = shift;
> >}
> >othermodule::set_global 7;
> >=============================================================================
> >Then, to my surprise, _sometimes_ the $global will be set, and sometimes not.
> 
> You know, if I didn't know any better, I'd say that you're simply setting
> $global (not the best name) in one httpd child, but of course it's not getting

No, it's completely deterministic ("sometimes" == depending on the when
the function was compiled). The technical aspect is clear (to me at
least, but I am bad at explaining ;): the file is sourced twice, and the
function is compiled twice (and since each "my" generates another instance
of a lexical, there are two variables).

The problem is that some code that was compiled "in between" (i.e. after
the first compilation and before the second) gets "bound" to the first
version of the function (think of it as a kind of callback). This means
that some modifications are not seen by my module.

This is indeed related to config-file-parsing.

As a related note, I wondered why there isn't a mod_perl callback that is
clled _before_ forking, but after configuration parsing. This would allow
a lot of data sharing between the httpd servers. My module requires you to
call "configured PApp" at the end of the configuration section so that it
can pull in most of the code and big data structures before it forks (so
the data gets shared). AFAIK there is no way to make this automatic.

> >Then, when the file is parsed again, _another_ instance of $global gets
> >created, and another instance of set_global is compiled. Now there are two
> >versions of set_global, two versions of $global, and which one gets called
> >very much depends on random factors.
> 
> I don't think I believe that.

You won't believe how long it took until _I_ believed that!!

> Nothing gets parsed twice except http configuration files.  Is this file
> used inside <perl> sections of config files, maybe?

"Used"? I definitely call it from within my perl sections, but it's not
embedded there (see the httpd.conf excerpt I posted). What happens is
that, somehow, %INC get's reset so perl thinks it hasn't loaded the module
yet, and just loads it again.

Ok, I tried a little bit and hopefully here is a small example that is
reproducible. Install this module as "X.pm" somewhere where mod_perl will
find it:

=============================================================================
package X;

my $x;
$g;
my $o;

BEGIN { 
   $d = defined &X::x;
   $o = &x if $d;
   $x++; $g++;
}

open FILE, ">>/tmp/log";
print FILE "hello pid=$$ x=$x g=$g d=$d o=$o\n";
close FILE;

sub x { $x }
=============================================================================

And use this httpd.conf:

=============================================================================
ServerType standalone
PerlFreshRestart On
HostnameLookups off

Port 83

ServerRoot /tmp
ErrorLog error

PerlModule X
=============================================================================

And then start httpd (I had to create conf/mime.types and a logs directory
to make apache run). Then look at the file /tmp/log:

cerebro:/tmp# rm /tmp/log; httpd -f /tmp/httpd.conf; sleep 1; cat /tmp/log
hello pid=32011 x=1 g=1 d= o=
hello pid=32011 x=1 g=2 d=1 o=1

The module is indeed compiled twice. Please note that, on the first time,
X::x is not yet defined (it wasn't compiled yet) but on the second time,
it is ($d==1). Also note that the global "$g" isn't changed (it survives,
as expected), while "$x" (a lexical) is allocated anew. However, a call
to the previous version of X::x returns the old value, i.e. o=1 (X::x is
still bound to the old copy since it wasn't recompiled yet, even if "$x"
is undefined at this moment).

I assumed it _had_ something to do with parsing twice, but, in fact, it
happens without using a perl section. My mod_perl is configured like this:

=============================================================================
PERL_SECTIONS=1
PERL_STACKED_HANDLERS=1
PERL_DIRECTIVE_HANDLERS=1
PERL_RESTART=1
PERL_AUTHEN=1
PERL_AUTHZ=1
PERL_TYPE=1
DO_HTTPD=1
=============================================================================

Am I the only one who thinks that

   {
      my $x = ...;
      sub the_only_function_using_x {
      }
   }

is cleaner then using a global variable? Heck, it's even recommended by
the perl documentation!

-- 
      -----==-                                             |
      ----==-- _                                           |
      ---==---(_)__  __ ____  __       Marc Lehmann      +--
      --==---/ / _ \/ // /\ \/ /       [EMAIL PROTECTED] |e|
      -=====/_/_//_/\_,_/ /_/\_\       XX11-RIPE         --+
    The choice of a GNU generation                       |
                                                         |

Reply via email to