On Tue, 23 May 2000, Marc Lehmann wrote:
> 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 a combination of closures and PerlFreshRestart biting
you.  Ordinarily, it wouldn't matter that you were making closures because
the main section of your module (outside of subs) would not be run
again.

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

Most people do a "PerlRequire startup.pl" and then put all that stuff in
startup.pl, which runs before the fork.  It will not be run twice because
PerlRequire will see it in %INC, unless you use PerlFreshRestart.

> =============================================================================
> 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).

Your sub &x is a closure.  That's why it returns the previous value of
$x.  When it gets re-defined, it should start looking at the value of the
new $x.

- Perrin

Reply via email to