perl-modperl mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From André Warnier ...@ice-sa.com>
Subject Re: Getting a / when regex should produce nothing
Date Tue, 27 Apr 2010 11:16:23 GMT
Michael Ludwig wrote:
> Moin André,
> 
> Am 26.04.2010 um 21:44 schrieb André Warnier:
>> craig@animalhead.com wrote:
>>> The retention of values from previous executions applies
>>> only to global variables.
>> Ah, yes.
>> But that would have triggered another discussion (which it might now 
>> still do of course), about what exactly /is/ a global variable, in the 
>> context of a mod_perl handler or perl script run under modperl::Registry.
> 
> Let's first clarify it for Perl in general, and then for mod_perl.
> 
> A global variable in Perl is any variable not declared with "my". Which includes variables
declared with "our" or "use vars" (I'll get to these), and also variables created by full
qualification, as in "$Bla::Blub = 1".
> 
> A lexical variable in Perl is any variable declared with "my", regardless of the scope,
which may be file-level. Unlike globals, lexical variables aren't directly accessible from
outside the package.
> 
> A global variable declared (or introduced, or admitted) with "use vars" is in scope for
the entire package where it is declared. A global variable declared with "our" is in scope
only for the lexical scope where it is declared (see "perldoc -f our").
> 
> (There's also "local", a misnomer, to temporarily stash away the current value of a global
variable and shadow it with another value. We can leave it out of the picture here.)
> 
> Now, how is this different for mod_perl? Well, it isn't, if you think about it, or rather
it boils down to the difference between a mod_perl handler and your typical batch script.
Your batch script is invoked, it runs, and ends. Running it probably includes some initialization
code of yours placed at the file level. Next time around, the whole thing start anew. Nothing
special here.
> 
> A mod_perl handler, as you know, is loaded once, and unless it is reloaded, is only acted
upon by invocation of its functions, such as handler(). Which means that reinitialization
doesn't happen automatically, as with your batch script running in a new process each time.
> 
> So what does this mean for file level lexical variables (my-variables) you have defined?
Well, they don't get reinitialized (unless you provide code to do so), so they start behaving
like global variables, retaining state between invocations. They are not, however, accessible
from outside the current package, so they're still lexical variables.
> 
> There's one more thing to understand, especially in the context of Apache::Registry and
Apache2::Registry, and that's lexical "my" variables referenced from nested names subroutines.
You do not usually create nested named subroutines, but the Registry handler does it for you
by wrapping your registry script in a handler subroutine in a package made up from the filesystem
path of rour registry script. So if you define a registry script with a subroutine that references
a lexical variable from the enclosing scope, you'll see the familiar warning message "Variable
"$x" will not stay shared".
> 
> You can read up about this issue here:
> 
> http://perl.apache.org/docs/general/perl_reference/perl_reference.html
> 
> Hope this helps :-)
> 

Very nice.  And it does help my understanding.
Although the key paragraph here, I would say, is :

So what does this mean for file level lexical variables (my-variables)
you have defined? Well, they don't get reinitialized (unless you provide
code to do so), so they start behaving like global variables, retaining
state between invocations. They are not, however, accessible from
outside the current package, so they're still lexical variables.

Let me give an example of how I understand this, for mod_perl handler 
packages :

# -- start of code --
package My::Something;

my $lexical_mine;

sub access {
my $r = shift;

if (defined($lexical_mine) {
   $r->log_error("in access: value present : $lexical_mine);
   $lexical_mine++;
} else {
   $lexical_mine = 1;
   $r->log_error("in access: initialised to : $lexical_mine);
}
return OK;
}

sub response {
my $r = shift;
if (defined($lexical_mine) {
   $r->log_error("in response: value present : $lexical_mine);
   $lexical_mine++;
} else {
   $lexical_mine = 1;
   $r->log_error("in response: initialised to : $lexical_mine);
}
# .. generate some response for the browser

return OK;
}

sub finalise {
my $r = shift;
my $lexical_mine;
if (defined($lexical_mine) {
   $r->log_error("in finalise: value present : $lexical_mine);
   $lexical_mine++;
} else {
   $lexical_mine = 1;
   $r->log_error("in finalise: initialised to : $lexical_mine);
}
return OK;
}


# -- end of code --

Now if I configure the first of these subs as a PerlAccessHandler and
the second as a PerlResponseHandler, what happens to $lexical_mine ?
It might be lexical, in the sense that there is no way for code in
another file, to access this variable from outside as, for example,
$My::Something::lexical_mine

But for all intents and purposes, this variable is "functionally
global", in the sense that throughout the life of the Apache child that
contains this perl interpreter, this variable is "shared", not only by
the separate handler subs, but even by subsequent invocations of these
subs in the course of processing all HTTP requests which happen to be
processed by this Apache child.(*)

On the other hand, if I configure "finalise" as a PerlSomethingHandler,
then the $lexical_mine that is defined inside it, does not play along
with the other one.  It is its own thing, and it will print its own
incremental sequence 1,1,2,3,4,5
But it is still "global" in a sense : while "private" to the sub
"finalise", it nevertheless is shared between consecutive invocations of
the same finalise() sub by the same Apache child.

So I guess what I mean is :

"global" and "lexical", as you use the terms above and as they are used
in the perl documentation (and no doubt rightly so), refer to scoping in
the sense of "how can I / can I not access that variable from outside of
the block/file where it is declared, using a "name" for it in my code.

However, for someone starting with perl and mod_perl, the term "global"
has a tendency to be interpreted as "shared between the handler subs
which I define in my package while they successively handle various
stages of one request", or even "shared between different invocations of
these handler subs for different requests", or even as "shared by all
handler subs processing all requests to this Apache".
(The last one being impossible with prefork).

So, back to the basics, my interpretation : by default, consider any 
variable as "global/shared" and you'll generally stay out of trouble.



(*) which is going to be very confusing in the logfile however, as for
now there is no way to distinguish which child logs a message.
For that, we might want to add ($$) to the log messages.






Mime
View raw message