Re: global variables and reparsing (short reproducible example)

2000-11-25 Thread Stas Bekman

On 24 May 2000, Randal L. Schwartz wrote:

  "tayers" ==   [EMAIL PROTECTED] writes:
 
 tayers Given the above more complete descriptions I would say the usage in
 tayers Lperlsub is confusing. 
 
 I agree with that, and with your general observation.  From my hanging
 out on P5P, a subroutine is only a closure when it sees lexical
 variables and must therefore create a distinct clone of the
 environment on the way out.
 
 And both named subroutines and anonymous subroutines can be closures.
 
 Here's how to tell if a subroutine is a closure or not:
 
 for (1..5) {
   push @a, sub { "hi there" };
 }
 for (1..5) {
   {
 my $b;
 push @b, sub { $b."hi there" };
   }
 }
 print "anon normal: @a\n";
 print "anon closure: @b\n";
 
 which generates
 
 anon normal: CODE(0x80ce9d4) CODE(0x80ce9d4) CODE(0x80ce9d4) CODE(0x80ce9d4) 
CODE(0x80ce9d4)
 anon closure: CODE(0x80c83ac) CODE(0x80d2440) CODE(0x80d24a0) CODE(0x80d2500) 
CODE(0x80d2560)
 
 Note how each coderef from the non-closure is identical, but the
 closure form must generate distinct coderefs to point at the distinct
 instances of the closure.
 
 This is the underpinnings of that famous "won't stay shared" message.
 A "my" variable in a named subroutine context is generating distinct
 coderefs.
 
 So, in summary, "closure" vs "non-closure", and "named subroutine" vs
 "anonymous subroutine" are orthogonal concepts.  Pick one from each
 column. :) And it's too bad that we have people mixing the terms up,
 because cargo-cult meme virus items spread fast in the Perl extended
 community.

Well, it's been about 6 months ago when Randal wrote this, but only now
I've finally got the time to reply to this. That's why the whole post is
quoted.

Apparently, the above explanation is not so complete and clear and while
"closure" vs "non-closure", and "named subroutine" vs "anonymous
subroutine" are indeed orthogonal concepts, only the "closure"+"anonymous
subroutine" appears to work, and "closure"+"named subroutine" is something
that should never happen, unless it's a desired effect and then the
programmer knows what's he doing.

Here is the part that Randal didn't post:

And now the same with named subroutines:

  for (1..5) {
sub a { "hi there" };
push @a, \a;
  }
  for (1..5) {
{
  my $b;
  sub b { $b."hi there" };
  push @b, \b;
}
  }
  print "normal:\n", join "\t\n",@a,"\n";
  print "closure:\n",join "\t\n",@b,"\n";

which generates:

  anon normal:
  CODE(0x80568c0)   
  CODE(0x80568c0)   
  CODE(0x80568c0)   
  CODE(0x80568c0)   
  CODE(0x80568c0)   
  
  anon closure:
  CODE(0x8056998)   
  CODE(0x8056998)   
  CODE(0x8056998)   
  CODE(0x8056998)   
  CODE(0x8056998)   

We can see that both versions has generated the same code reference. For
the subroutine Ia it's easy, since it doesn't include any lexical
variables defined outside it in the same lexical scope. 

As for the subroutine Ib, it's indeed a closure sub, but Perl won't
recompile it since it's a named subroutine (see the perlsub manpage). It's
something that we don't want to happen in our code.

This is the underpinnings of that famous I"won't stay shared" message.  
A Imy variable in a named subroutine context is generating identical
code references and therefore it ignores any future changes to the lexical
variables outside of it.

BTW, for those who aren't yet familiar with the famous I"won't stay
shared" message and the prove that "closure"+"anonymous subroutine" work,
please read:
http://perl.apache.org/guide/perl.html#my_Scoped_Variable_in_Nested_S

Thanks!

_
Stas Bekman  JAm_pH --   Just Another mod_perl Hacker
http://stason.org/   mod_perl Guide  http://perl.apache.org/guide 
mailto:[EMAIL PROTECTED]   http://apachetoday.com http://jazzvalley.com
http://singlesheaven.com http://perl.apache.org http://perlmonth.com/  



-
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]




Re: global variables and reparsing (short reproducible example)

2000-06-01 Thread Doug MacEachern

On Fri, 26 May 2000, Marc Lehmann wrote:

 On Thu, May 25, 2000 at 12:09:09PM -0700, Doug MacEachern [EMAIL PROTECTED] wrote:
   You can only configure Apache from Perl sections, but you can load all
   your modules, shared data, etc. from a file pulled in with PerlRequire.
  
  actually you can, if a module defines variables in the
  Apache::ReadConfig:: namespace, they are fed to the apache config gears
  just as Perl sections are.
 
 Erhm, I am doing this right now (the functions I call just implant
 Location directives etc.. into the caller's package).
 
 Now it would be interesting to know wether that works only when called from
 perl sections or also form perlrequire? (Hmm, I'll just try it out and assume
 it's supported if it works ;)

yes, it's supported with PerlRequire and PerlModule.




Re: global variables and reparsing (short reproducible example)

2000-05-25 Thread Doug MacEachern

On Wed, 24 May 2000, Perrin Harkins wrote:

 On Wed, 24 May 2000, Marc Lehmann wrote:
  I was under the impression that you cannot configure Apache from a
  PerlRequire. If that is not the case (and somehow works) I'd really like
  to get away from perlsections.
 
 You can only configure Apache from Perl sections, but you can load all
 your modules, shared data, etc. from a file pulled in with PerlRequire.

actually you can, if a module defines variables in the
Apache::ReadConfig:: namespace, they are fed to the apache config gears
just as Perl sections are.




Re: global variables and reparsing (short reproducible example)

2000-05-25 Thread Marc Lehmann

On Thu, May 25, 2000 at 12:09:09PM -0700, Doug MacEachern [EMAIL PROTECTED] wrote:
  You can only configure Apache from Perl sections, but you can load all
  your modules, shared data, etc. from a file pulled in with PerlRequire.
 
 actually you can, if a module defines variables in the
 Apache::ReadConfig:: namespace, they are fed to the apache config gears
 just as Perl sections are.

Erhm, I am doing this right now (the functions I call just implant
Location directives etc.. into the caller's package).

Now it would be interesting to know wether that works only when called from
perl sections or also form perlrequire? (Hmm, I'll just try it out and assume
it's supported if it works ;)

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



Re: global variables and reparsing (short reproducible example)

2000-05-24 Thread Marc Lehmann

On Tue, May 23, 2000 at 04:07:40PM -0700, Perrin Harkins [EMAIL PROTECTED] wrote:
 This is a combination of closures and PerlFreshRestart biting
(still no closures)

My example might be misleading, since I used x before it was defined (to make
the example short). Typical examples look like this:

my $global1;

sub func1_using_global1 {
}

sub func2_using_global2_and_func1 {
}
 
etc... Users of the module outside the module itself can get incosistent
views about which fucntion accesses which global.

 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.

I was under the impression that you cannot configure Apache from a
PerlRequire. If that is not the case (and somehow works) I'd really like
to get away from perlsections.

 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.

You cannot redefine closures as well.

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



Re: global variables and reparsing (short reproducible example)

2000-05-24 Thread Marc Lehmann

On Wed, May 24, 2000 at 12:52:37AM +0300, Stas Bekman [EMAIL PROTECTED] wrote:
You can control what's being reloaded and what's not:
http://perl.apache.org/guide/config.html#Apache_Restarts_Twice_On_Start   
   

Not really. This would require intimate knowledge of some module's
implementation (which files it requires and which it doesn't). My hackish
example did something similar, indeed, but it had to be embedded into the
module source, which is somewhat inconvinient.

BTW, what is the connection between that part of config.html and
PerlFreshRestart? Can it happen that modules get reparsed even when
PerlFreshRestart is off? Should I abstain from trying to restart apache
when using any modules requiring full perl semantics? And is SIGUSR1 safe?

(Sorry, so many questions..  :)

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



Re: global variables and reparsing (short reproducible example)

2000-05-24 Thread Marc Lehmann

On Tue, 23 May 2000, Perrin Harkins wrote:

 Your sub x is a closure.  That's why it returns the previous value of

No. In perl, a closure is *defined* as "anonymous subroutine" (see the
documentation). If you define it different, you are right, but you are not
talking about perl then.

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



Re: global variables and reparsing (short reproducible example)

2000-05-24 Thread Randal L. Schwartz

 "tayers" ==   [EMAIL PROTECTED] writes:

tayers Given the above more complete descriptions I would say the usage in
tayers Lperlsub is confusing. 

I agree with that, and with your general observation.  From my hanging
out on P5P, a subroutine is only a closure when it sees lexical
variables and must therefore create a distinct clone of the
environment on the way out.

And both named subroutines and anonymous subroutines can be closures.

Here's how to tell if a subroutine is a closure or not:

for (1..5) {
  push @a, sub { "hi there" };
}
for (1..5) {
  {
my $b;
push @b, sub { $b."hi there" };
  }
}
print "anon normal: @a\n";
print "anon closure: @b\n";

which generates

anon normal: CODE(0x80ce9d4) CODE(0x80ce9d4) CODE(0x80ce9d4) CODE(0x80ce9d4) 
CODE(0x80ce9d4)
anon closure: CODE(0x80c83ac) CODE(0x80d2440) CODE(0x80d24a0) CODE(0x80d2500) 
CODE(0x80d2560)

Note how each coderef from the non-closure is identical, but the
closure form must generate distinct coderefs to point at the distinct
instances of the closure.

This is the underpinnings of that famous "won't stay shared" message.
A "my" variable in a named subroutine context is generating distinct
coderefs.

So, in summary, "closure" vs "non-closure", and "named subroutine" vs
"anonymous subroutine" are orthogonal concepts.  Pick one from each
column. :) And it's too bad that we have people mixing the terms up,
because cargo-cult meme virus items spread fast in the Perl extended
community.

-- 
Randal L. Schwartz - Stonehenge Consulting Services, Inc. - +1 503 777 0095
[EMAIL PROTECTED] URL:http://www.stonehenge.com/merlyn/
Perl/Unix/security consulting, Technical writing, Comedy, etc. etc.
See PerlTraining.Stonehenge.com for onsite and open-enrollment Perl training!



Re: global variables and reparsing (short reproducible example)

2000-05-24 Thread Perrin Harkins

On Wed, 24 May 2000, Marc Lehmann wrote:

 On Wed, May 24, 2000 at 12:52:37AM +0300, Stas Bekman [EMAIL PROTECTED] wrote:
 You can control what's being reloaded and what's not:
 http://perl.apache.org/guide/config.html#Apache_Restarts_Twice_On_Start 
 
 
 Not really. This would require intimate knowledge of some module's
 implementation (which files it requires and which it doesn't). My hackish
 example did something similar, indeed, but it had to be embedded into the
 module source, which is somewhat inconvinient.

If you don't have PerlFreshRestart turned on (it is not recommended on
production servers), only the stuff in your config file (Perl sections
and PerlModule/PerlRequire) gets called twice.  You can block things out
like this:

Perl
unless ($Apache::Server::ReStarting) {
  ...
}
/Perl

 BTW, what is the connection between that part of config.html and
 PerlFreshRestart? Can it happen that modules get reparsed even when
 PerlFreshRestart is off?

Only the stuff in your config file should get reparsed.

 Should I abstain from trying to restart apache when using any modules
 requiring full perl semantics? And is SIGUSR1 safe?

People have reported some growth in memory consumption when using
SUGUSR1.  Personally, I always do cold stop and start on my production
servers, in order to maximize shared memory, but this is difficult when
you don't have a load-balanced cluster at your disposal...

- Perrin




Re: global variables and reparsing (short reproducible example)

2000-05-24 Thread Perrin Harkins

On Wed, 24 May 2000, Marc Lehmann wrote:
 I was under the impression that you cannot configure Apache from a
 PerlRequire. If that is not the case (and somehow works) I'd really like
 to get away from perlsections.

You can only configure Apache from Perl sections, but you can load all
your modules, shared data, etc. from a file pulled in with PerlRequire.

  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.
 
 You cannot redefine closures as well.

Closures are a confusing aspect of perl, and I could easily be mistaken
about them, but Randal and Doug seem to agree that this is a closure:

my $x;

sub show_x {
  print $x;
}

The easiest definition I've found is the one that Damian Conway has in his
OO Perl book:

"In Perl, a closure is just a subroutine that refers to one or more
lexical variables declared outside the subroutine itself."

When this code gets parsed, the $x goes out of scope at the end of the
block, but show_x keeps a copy of it.

I think that this is the source of the behavior you saw where it looked
like there were multiple versions of subs and variables being created.

Anyway, I was just trying to help you solve your problem.  There's no need
to get defensive.

- Perrin




Re: global variables and reparsing (short reproducible example)

2000-05-24 Thread Marc Lehmann

On Wed, May 24, 2000 at 11:30:40AM -0700, Perrin Harkins [EMAIL PROTECTED] wrote:
  example did something similar, indeed, but it had to be embedded into the
  module source, which is somewhat inconvinient.
 
 If you don't have PerlFreshRestart turned on (it is not recommended on
 production servers), only the stuff in your config file (Perl sections
 and PerlModule/PerlRequire) gets called twice.  You can block things out
 like this:

Actually, and to my surprise, PerlModule/PerlRequire is not done twice,
at leats not with respect to reparsing. They simply don't reparse the
modules, so mod_perl works *perfectly* without PerlFreshRestart, and
without special measures.

 SUGUSR1.  Personally, I always do cold stop and start on my production
 servers, in order to maximize shared memory, but this is difficult when
 you don't have a load-balanced cluster at your disposal...

*) It's also more disruptive ;)

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



global variables and reparsing (short reproducible example)

2000-05-23 Thread Marc Lehmann

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



Re: global variables and reparsing (short reproducible example)

2000-05-23 Thread Doug MacEachern

On Tue, 23 May 2000, Marc Lehmann wrote:
 
 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.

what's wrong with having 'PerlModule foo' at the bottom of your config
file?  apache 1.3 has no 'post-config' hook, 2.0 does though.
 
  Then, when the file is parsed again, _another_ instance of $global gets

 PerlFreshRestart On
 PerlModule X
 
 The module is indeed compiled twice.

yes, because apache does module-init/config-read twice at startup, since
you have 'PerlFreshRestart On', your module is re-compiled on this second
pass.




Re: global variables and reparsing (short reproducible example)

2000-05-23 Thread Marc Lehmann

On Tue, May 23, 2000 at 11:53:04AM -0700, Doug MacEachern [EMAIL PROTECTED] wrote:
  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.
 
 what's wrong with having 'PerlModule foo' at the bottom of your config

Nothing. It's just that users of my module constantly forget that ;)

 file?  apache 1.3 has no 'post-config' hook, 2.0 does though.

Another non-issue, then ;)

  PerlFreshRestart On
  PerlModule X
 
 yes, because apache does module-init/config-read twice at startup, since
 you have 'PerlFreshRestart On', your module is re-compiled on this second

BINGO, exactly. Thanks a lot for clarifying!! Here is a proposed extension
for perldoc mod_perl / RESTARTING:

 PerlFreshRestart On

Please note that setting this option results in parsing your modules
twice at server startup, and reparsing at every restart. Old code and
variables are not cleared and might interfere with your module. Avoiding
lexical variables at global scope and not referencing subs before
declaration/definition is therefore recommended.

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



Re: global variables and reparsing (short reproducible example)

2000-05-23 Thread Doug MacEachern

On Tue, 23 May 2000, Perrin Harkins wrote:

 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.

nevermind what i said in the other reply about not being a closure.
you're right, it is by definition, i just assumed you were refering to the
Apache::Registry trap.