lexical scoping under mod perl solution

lexical scoping under mod perl solution

am 12.02.2009 16:52:38 von earonesty

(A solution would be to force all "my" varialbes at the file scope to
be "our" and then put the cgi in an anonymous package:)

On Thu, Feb 12, 2009 at 10:33 AM, Erik Aronesty wrote:
> -------------8<---------- Start Bug Report ------------8<----------
> 1. Problem Description:
>
> It's well known that file-scoped lexicals don't work intuitively in
> CGI programs under mod_perl.
>
> When mod_perl calls the same CGI program twice, file-scoped lexicals
> are not rebound.
>
> Some people are aware of this, random posts to newsgroups will attest,
> but this is not documented well enough.
>
> Create a CGI as below, and run it many times, assigning different
> CGI::param('foo') values to $x.
> Lowering the number of children spawned in Apache will reduce the
> number of times needed
> to run the script in order to see the problem.
>
> # this program sometimes prints old values for foo, but only under mod_perl!
>
> use CGI;
> my $x =CGI::param('foo');

Re: lexical scoping under mod perl solution

am 12.02.2009 17:12:53 von Adam Prime

Erik Aronesty wrote:
> (A solution would be to force all "my" varialbes at the file scope to
> be "our" and then put the cgi in an anonymous package:)
>
> On Thu, Feb 12, 2009 at 10:33 AM, Erik Aronesty wrote:
>> -------------8<---------- Start Bug Report ------------8<----------
>> 1. Problem Description:
>>
>> It's well known that file-scoped lexicals don't work intuitively in
>> CGI programs under mod_perl.
>>
>> When mod_perl calls the same CGI program twice, file-scoped lexicals
>> are not rebound.
>>
>> Some people are aware of this, random posts to newsgroups will attest,
>> but this is not documented well enough.
>>
>> Create a CGI as below, and run it many times, assigning different
>> CGI::param('foo') values to $x.
>> Lowering the number of children spawned in Apache will reduce the
>> number of times needed
>> to run the script in order to see the problem.
>>
>> # this program sometimes prints old values for foo, but only under mod_perl!
>>
>> use CGI;
>> my $x =CGI::param('foo');

I assume that you're running under ModPerl::Registry, since you haven't
specified otherwise, is that actually the case? If it is, I'd encourage
you to try running under ModPerl::PerlRun instead, which does a better
job of emulating CGI (at the expense of speed).

You are absolutely right though that this should be explicitly noted in
the documentation for Registry (and possibly PerlRun, if it doesn't work
there either). I personally very rarely use CGI emulation, so i'm not
entirely sure what does and doesn't work.

Adam

Re: lexical scoping under mod perl solution

am 12.02.2009 17:13:55 von mpeters

Erik Aronesty wrote:
> (A solution would be to force all "my" varialbes at the file scope to
> be "our" and then put the cgi in an anonymous package:)

A file/package-scoped "my" var is not the same thing as an "our" var. One example is that a "my" var
can't be seen outside of the package/scope it's in. A package level "our" var can be seen.

--
Michael Peters
Plus Three, LP

Re: lexical scoping under mod perl solution

am 12.02.2009 20:30:21 von Erik Aronesty

>> (A solution would be to force all "my" varialbes at the file scope to
>> be "our" and then put the cgi in an anonymous package:)
>
> A file/package-scoped "my" var is not the same thing as an "our" var. One
> example is that a "my" var can't be seen outside of the package/scope it's
> in. A package level "our" var can be seen.

Yes, I know. Hence the anonymous, unnamed package idea.

But it's really silly. Better warnings or more clear docs would be sufficient.

Just the concept that a top-level $my isn't good enough to localize a
variable seems to boggle until you realize what ::Registry is doing.

Re: lexical scoping under mod perl solution

am 12.02.2009 21:34:07 von aw

As someone pointed out, these things can be very practical too.

#-----------
#!/usr/bin/perl
# my nifty cgi-bin

use strict;
use warnings;

our $big_table;

{
package XX;
no strict;
$var1 = 0;
}

sub sub1 {
my $key = shift;

unless (defined($big_table)) {
go_fill_it($big_table);
$XX::var1++;
}
if ($XX::var1) {
return $big_table->{$key};
}
return undef;
}

sub sub2 {
my $key = shift;

}
....


#----------

The $big_table var (and the underlying hash) will be initialised the
first time the above mod_perl handler (or cgi-bin script under mod_perl)
gets called /in this apache child/. Then it will retain its value
across multiple invocations (http requests) /within this apache child/,
as long as the child is alive (thus potentially saving hundreds of
reloads of the big table).
$XX::var1 on the other hand, is really local to this running script
instance, but global to the subs within it.
$key is really local to each sub in all respects.

Beauty is in the eyes of the beholder.
Perl and mod_perl may not be appreciated by the purists, but it's neat
what you can do with them.

I'd love to have something like the above that works /multi-platform/
*across* different apache children/threads.
Perhaps based on DBI...