CGI.pm param and mod_perl

CGI.pm param and mod_perl

am 13.06.2008 20:39:13 von Brian Gaber

This is a multi-part message in MIME format.

------_=_NextPart_001_01C8CD84.C68EF8BD
Content-Type: text/plain;
charset="US-ASCII"
Content-Transfer-Encoding: quoted-printable

I have converted a CGI.pm cgi-bin script to run in mod_perl as a
Registry. On multiple runs I seem to get old values of a param('var').
I have read the documents and understand I need to be careful with
global variables. Is there something I need to be aware of when I use
CGI.pm params? One thought, my code is written to use the CGI.pm
default object so that I do not have something like $q =3D new CGI; =
Could
this be the cuase?

Thanks.

Brian

------_=_NextPart_001_01C8CD84.C68EF8BD
Content-Type: text/html;
charset="US-ASCII"
Content-Transfer-Encoding: quoted-printable




charset=3Dus-ascii">
6.5.7652.24">
CGI.pm param and mod_perl




I have converted a =
CGI.pm cgi-bin script to run in mod_perl as a Registry.  On =
multiple runs I seem to get old values of a param('var').  I have =
read the documents and understand I need to be careful with global =
variables.  Is there something I need to be aware of when I use =
CGI.pm params?  One thought, my code is written to use the CGI.pm =
default object so that I do not have something like $q =3D new =
CGI;  Could this be the cuase?



FACE=3D"Arial">Thanks.



FACE=3D"Arial">Brian





------_=_NextPart_001_01C8CD84.C68EF8BD--

Re: CGI.pm param and mod_perl

am 13.06.2008 20:53:37 von mpeters

Brian Gaber wrote:
> One thought, my code is written to use the CGI.pm
> default object so that I do not have something like $q = new CGI; Could
> this be the cuase?

Very well could be.

Doing a "$q = new CGI" means that you will get a new CGI object on every
request, which is what you want. I've never used the function interface of
CGI.pm like you did in your example so I don't know how CGI.pm handles it behind
the scenes (whether it creates a new object on each request or not). But if I
were you, that's probably the first place I'd look.

Also, just a couple of minor nits to help you out. Instead of "$q = new CGI" do
"my $q = CGI->new()". First off the "my" means it's a local (lexical) variable.
Always good to have your vars be local unless you know you'll need something
else. And "new CGI" is the indirect object syntax for method calls which is
generally frowned upon since it can lead to problems that are hard to track
down. "CGI->new()" is alway unambiguous.

--
Michael Peters
Plus Three, LP

RE: CGI.pm param and mod_perl

am 13.06.2008 21:16:09 von Brian Gaber

Michael,

Using $q was not successful. Here is what I have done:

use vars qw($q);

$q =3D CGI->new();

sub print_form {
my $dept2show =3D 'A';
=20
if ( $q->param('deptLtr') ) {
($dept2show) =3D $q->param('deptLtr') =3D~ /^([a-zA-Z]{1})$/;
}=20


I am running this script simultaneously on two PCs. Sometimes
$dept2show has the expected value, but often is has the an old value.

-----Original Message-----
From: Michael Peters [mailto:mpeters@plusthree.com]=20
Sent: Friday, June 13, 2008 2:54 PM
To: Brian Gaber
Cc: modperl@perl.apache.org
Subject: Re: CGI.pm param and mod_perl

Brian Gaber wrote:
> One thought, my code is written to use the CGI.pm default object so=20
> that I do not have something like $q =3D new CGI; Could this be the=20
> cuase?

Very well could be.

Doing a "$q =3D new CGI" means that you will get a new CGI object on =
every
request, which is what you want. I've never used the function interface
of CGI.pm like you did in your example so I don't know how CGI.pm
handles it behind the scenes (whether it creates a new object on each
request or not). But if I were you, that's probably the first place I'd
look.

Also, just a couple of minor nits to help you out. Instead of "$q =3D =
new
CGI" do "my $q =3D CGI->new()". First off the "my" means it's a local
(lexical) variable.
Always good to have your vars be local unless you know you'll need
something else. And "new CGI" is the indirect object syntax for method
calls which is generally frowned upon since it can lead to problems that
are hard to track down. "CGI->new()" is alway unambiguous.

--
Michael Peters
Plus Three, LP

Re: CGI.pm param and mod_perl

am 13.06.2008 21:20:59 von mpeters

Brian Gaber wrote:
> Using $q was not successful.

That's because you ignored my advice :)

> Here is what I have done:
>
> use vars qw($q);

That makes $q a global. Bad, bad, very bad. Slap yourself on the wrist. Remove
that "use vars" line.

> $q = CGI->new();

Now replace that with

my $q = CGI->new();

> sub print_form {
> my $dept2show = 'A';
>
> if ( $q->param('deptLtr') ) {
> ($dept2show) = $q->param('deptLtr') =~ /^([a-zA-Z]{1})$/;
> }
>
>
> I am running this script simultaneously on two PCs. Sometimes
> $dept2show has the expected value, but often is has the an old value.

This is because Apache is using multiple processes to handle things. Sometimes
you're hitting a process for the first time, so it creates an new CGI object and
all is well. But sometimes your request goes back to a process that has already
loaded and executed this code before, so $q is not a new CGI object.

--
Michael Peters
Plus Three, LP

RE: CGI.pm param and mod_perl

am 13.06.2008 21:34:30 von Brian Gaber

I just did as you suggested.

Now in the log I get a

Variable "$q" will not stay shared at ...

error from the $q->param('deptLtr') in the subroutine.

When I read the mod_perl docs they suggest that use vars was one
approach to fix the "Variable X will not stay shared at" error.

What is the recommended approach? Pass a reference to $q?

Thanks

-----Original Message-----
From: Michael Peters [mailto:mpeters@plusthree.com]=20
Sent: Friday, June 13, 2008 3:21 PM
To: Brian Gaber
Cc: modperl@perl.apache.org
Subject: Re: CGI.pm param and mod_perl

Brian Gaber wrote:
> Using $q was not successful.=20

That's because you ignored my advice :)

> Here is what I have done:
>=20
> use vars qw($q);

That makes $q a global. Bad, bad, very bad. Slap yourself on the wrist.
Remove that "use vars" line.

> $q =3D CGI->new();

Now replace that with

my $q =3D CGI->new();

> sub print_form {
> my $dept2show =3D 'A';
> =20
> if ( $q->param('deptLtr') ) {
> ($dept2show) =3D $q->param('deptLtr') =3D~ /^([a-zA-Z]{1})$/;
> }
>=20
>=20
> I am running this script simultaneously on two PCs. Sometimes=20
> $dept2show has the expected value, but often is has the an old value.

This is because Apache is using multiple processes to handle things.
Sometimes you're hitting a process for the first time, so it creates an
new CGI object and all is well. But sometimes your request goes back to
a process that has already loaded and executed this code before, so $q
is not a new CGI object.

--
Michael Peters
Plus Three, LP

Re: CGI.pm param and mod_perl

am 13.06.2008 21:35:10 von mpeters

Brian Gaber wrote:

> When I read the mod_perl docs they suggest that use vars was one
> approach to fix the "Variable X will not stay shared at" error.

This makes me think that maybe your problem is something else... but try below.

> What is the recommended approach? Pass a reference to $q?

Not a reference, but $q itself (objects are already references, so passing a
reference to a reference doesn't gain anything). It's a good idea in just about
all programming languages to avoid globals and pass things around to subroutines
that need them.

--
Michael Peters
Plus Three, LP

Re: CGI.pm param and mod_perl

am 13.06.2008 21:37:35 von dstroma

Michael Peters wrote:
> Brian Gaber wrote:
>> Using $q was not successful.
>
> That's because you ignored my advice :)
>
>> Here is what I have done:
>>
>> use vars qw($q);
>
> That makes $q a global. Bad, bad, very bad. Slap yourself on the wrist.
> Remove
> that "use vars" line.

I don't see what is so bad about this:

use vars qw($q);
$q = CGI->new();

Even though it's a global variable, you are assigning it a new value,
CGI->new, each time.

On the other hand, a subroutine should never use a lexical variable that was
declared outside of it, at least not in a Registry type script because of
the nested subroutines. So this is very bad and should trigger a "variable
will not stay shared" warning:

my $q = CGI->new;
sub dostuff {
print $q->param('foobar');
}

I suspect the problem is something else, possibly part of the script that we
haven't seen.

Re: CGI.pm param and mod_perl

am 13.06.2008 21:47:18 von mpeters

Dondi Stroma wrote:

> I don't see what is so bad about this:
>
> use vars qw($q);
> $q = CGI->new();
>
> Even though it's a global variable, you are assigning it a new value,
> CGI->new, each time.

You're right. I don't normally think about registry scripts since I almost never
use them. I was thinking he was doing that at the top of a module such that it
was happening at compile time. But even then my advice wasn't that helpful since
the assignment would still only happen at compile time.

> I suspect the problem is something else, possibly part of the script
> that we haven't seen.

Yeah, I'm starting to think the same thing. Brian, why don't you print the value
of the param to the log ("warn" is good for this) for the request (along with
the SQL that you're generating) so you/we can see what the actual value being
pulled it.

--
Michael Peters
Plus Three, LP

RE: CGI.pm param and mod_perl

am 13.06.2008 22:08:30 von Brian Gaber

Michael,

Here is the log you asked for:

The value of region is Atlantic
The value of set is 0
SELECT * FROM atlantic_rr WHERE dept REGEXP '^A' ORDER BY dept, pay_list
LIMIT 0, 400
The value of region is Atlantic
The value of deptLtr is I
The value of set is 0
SELECT * FROM atlantic_rr WHERE dept REGEXP '^I' ORDER BY dept, pay_list
The value of region is Atlantic
The value of deptLtr is O
The value of set is 0
SELECT * FROM atlantic_rr WHERE dept REGEXP '^O' ORDER BY dept, pay_list
The value of region is Atlantic
The value of set is 0
SELECT * FROM atlantic_rr WHERE dept REGEXP '^A' ORDER BY dept, pay_list
LIMIT 0, 400
The value of region is Atlantic
The value of deptLtr is K
The value of set is 0
SELECT * FROM atlantic_rr WHERE dept REGEXP '^K' ORDER BY dept, pay_list
The value of region is Atlantic
The value of deptLtr is F
The value of set is 0
SELECT * FROM atlantic_rr WHERE dept REGEXP '^F' ORDER BY dept, pay_list
The value of region is Atlantic
The value of deptLtr is F <- ERROR I selected C
The value of set is 0
SELECT * FROM atlantic_rr WHERE dept REGEXP '^F' ORDER BY dept, pay_list
The value of region is Atlantic
The value of deptLtr is O <- ERROR I selected C
The value of set is 0
SELECT * FROM atlantic_rr WHERE dept REGEXP '^O' ORDER BY dept, pay_list

Thanks.
-----Original Message-----
From: Michael Peters [mailto:mpeters@plusthree.com]=20
Sent: Friday, June 13, 2008 3:47 PM
To: Dondi Stroma
Cc: modperl@perl.apache.org
Subject: Re: CGI.pm param and mod_perl

Dondi Stroma wrote:

> I don't see what is so bad about this:
>=20
> use vars qw($q);
> $q =3D CGI->new();
>=20
> Even though it's a global variable, you are assigning it a new value,
> CGI->new, each time.

You're right. I don't normally think about registry scripts since I
almost never use them. I was thinking he was doing that at the top of a
module such that it was happening at compile time. But even then my
advice wasn't that helpful since the assignment would still only happen
at compile time.

> I suspect the problem is something else, possibly part of the script=20
> that we haven't seen.

Yeah, I'm starting to think the same thing. Brian, why don't you print
the value of the param to the log ("warn" is good for this) for the
request (along with the SQL that you're generating) so you/we can see
what the actual value being pulled it.

--
Michael Peters
Plus Three, LP

Re: CGI.pm param and mod_perl

am 13.06.2008 22:20:56 von mpeters

Brian Gaber wrote:

> Here is the log you asked for:

We need a little more context than that. For instance I don't see where it
actually has the fatal error you mentioned from the earlier posts. Also, if you
could annotate it with what the values of those params "should" be.

But the most important thing you can do is to reduce the problem down to the
smallest possible code that still has the fatal error. Not only will it help us
help you, but 90% of the time when I do that I figure out what the problem was
on my own.

--
Michael Peters
Plus Three, LP

RE: CGI.pm param and mod_perl

am 13.06.2008 22:21:23 von Brian Gaber

Sorry, my e-mail client didn't like the line endings of the log. Here
is the log agin in a more readable format:

The value of region is Atlantic
The value of set is 0
SELECT * FROM atlantic_rr WHERE dept REGEXP '^A' ORDER BY dept, pay_list
LIMIT 0, 400
The value of region is Atlantic
The value of deptLtr is I
The value of set is 0 SELECT * FROM atlantic_rr WHERE dept REGEXP '^I'
ORDER BY dept, pay_list
The value of region is Atlantic
The value of deptLtr is O
The value of set is 0
SELECT * FROM atlantic_rr WHERE dept REGEXP '^O' ORDER BY dept, pay_list
The value of region is Atlantic
The value of set is 0
SELECT * FROM atlantic_rr WHERE dept REGEXP '^A' ORDER BY dept, pay_list
LIMIT 0, 400
The value of region is Atlantic
The value of deptLtr is K
The value of set is 0
SELECT * FROM atlantic_rr WHERE dept REGEXP '^K' ORDER BY dept, pay_list
The value of region is Atlantic
The value of deptLtr is F
The value of set is 0
SELECT * FROM atlantic_rr WHERE dept REGEXP '^F' ORDER BY dept, pay_list
The value of region is Atlantic
The value of deptLtr is F <- ERROR I selected C
The value of set is 0
SELECT * FROM atlantic_rr WHERE dept REGEXP '^F' ORDER BY dept, pay_list
The value of region is Atlantic
The value of deptLtr is O <- ERROR I selected C
The value of set is 0
SELECT * FROM atlantic_rr WHERE dept REGEXP '^O' ORDER BY dept, pay_list

Thanks.=20

-----Original Message-----
From: Michael Peters [mailto:mpeters@plusthree.com]=20
Sent: Friday, June 13, 2008 3:47 PM
To: Dondi Stroma
Cc: modperl@perl.apache.org
Subject: Re: CGI.pm param and mod_perl

Dondi Stroma wrote:

> I don't see what is so bad about this:
>=20
> use vars qw($q);
> $q =3D CGI->new();
>=20
> Even though it's a global variable, you are assigning it a new value,
> CGI->new, each time.

You're right. I don't normally think about registry scripts since I
almost never use them. I was thinking he was doing that at the top of a
module such that it was happening at compile time. But even then my
advice wasn't that helpful since the assignment would still only happen
at compile time.

> I suspect the problem is something else, possibly part of the script=20
> that we haven't seen.

Yeah, I'm starting to think the same thing. Brian, why don't you print
the value of the param to the log ("warn" is good for this) for the
request (along with the SQL that you're generating) so you/we can see
what the actual value being pulled it.

--
Michael Peters
Plus Three, LP

RE: CGI.pm param and mod_perl

am 13.06.2008 22:31:26 von Brian Gaber

Michael,

The fatal errors from yesterday are fixed. When I run this as a
cgi-bin it runs fine.

The HTML code that I am selecting looks like this:














.... Etc (for each letter of the alphabet)

The value of region is Atlantic <- GOOD
The value of set is 0
SELECT * FROM atlantic_rr WHERE dept REGEXP '^A' ORDER BY dept, pay_list
LIMIT 0, 400

The value of region is Atlantic
The value of deptLtr is I <- GOOD
The value of set is 0 SELECT * FROM atlantic_rr WHERE dept REGEXP '^I'
ORDER BY dept, pay_list

The value of region is Atlantic
The value of deptLtr is O <- GOOD
The value of set is 0
SELECT * FROM atlantic_rr WHERE dept REGEXP '^O' ORDER BY dept, pay_list

The value of region is Atlantic <- GOOD
The value of set is 0
SELECT * FROM atlantic_rr WHERE dept REGEXP '^A' ORDER BY dept, pay_list
LIMIT 0, 400

The value of region is Atlantic
The value of deptLtr is K <- GOOD
The value of set is 0
SELECT * FROM atlantic_rr WHERE dept REGEXP '^K' ORDER BY dept, pay_list

The value of region is Atlantic
The value of deptLtr is F <- GOOD
The value of set is 0
SELECT * FROM atlantic_rr WHERE dept REGEXP '^F' ORDER BY dept, pay_list

The value of region is Atlantic
The value of deptLtr is F <- ERROR I selected C
The value of set is 0
SELECT * FROM atlantic_rr WHERE dept REGEXP '^F' ORDER BY dept, pay_list

The value of region is Atlantic
The value of deptLtr is O <- ERROR I selected C
The value of set is 0
SELECT * FROM atlantic_rr WHERE dept REGEXP '^O' ORDER BY dept, pay_list


-----Original Message-----
From: Michael Peters [mailto:mpeters@plusthree.com]=20
Sent: Friday, June 13, 2008 4:21 PM
To: Brian Gaber
Cc: Dondi Stroma; modperl@perl.apache.org
Subject: Re: CGI.pm param and mod_perl

Brian Gaber wrote:

> Here is the log you asked for:

We need a little more context than that. For instance I don't see where
it actually has the fatal error you mentioned from the earlier posts.
Also, if you could annotate it with what the values of those params
"should" be.

But the most important thing you can do is to reduce the problem down to
the smallest possible code that still has the fatal error. Not only will
it help us help you, but 90% of the time when I do that I figure out
what the problem was on my own.

--
Michael Peters
Plus Three, LP

Re: CGI.pm param and mod_perl

am 13.06.2008 22:38:03 von dstroma

Brian Gaber wrote:

> The HTML code that I am selecting looks like this:

That's not necessary. What does your perl code look like now? Also, try
printing/warning the value of $$, which is the process ID. I think you'll
find that the value of your variable stays the same for each process.

RE: CGI.pm param and mod_perl

am 13.06.2008 22:48:15 von Brian Gaber

Dondi,

Thanks for the advice. Here is the log output now:

The value of region is Atlantic for PID: 44538
The value of set is 0 for PID: 44538
SELECT * FROM atlantic_rr WHERE dept REGEXP '^A' ORDER BY dept, pay_list
LIMIT 0, 400

The value of region is Atlantic for PID: 60132
The value of deptLtr is G for PID: 60132
The value of set is 0 for PID: 60132 <- GOOD
SELECT * FROM atlantic_rr WHERE dept REGEXP '^G' ORDER BY dept, pay_list

The value of region is Atlantic for PID: 48600
The value of set is 0 for PID: 48600 <- GOOD
SELECT * FROM atlantic_rr WHERE dept REGEXP '^A' ORDER BY dept, pay_list
LIMIT 0, 400

The value of region is Atlantic for PID: 53446
The value of deptLtr is F for PID: 53446 <- GOOD
The value of set is 0 for PID: 53446
SELECT * FROM atlantic_rr WHERE dept REGEXP '^F' ORDER BY dept, pay_list

The value of region is Atlantic for PID: 53446
The value of deptLtr is F for PID: 53446 <- ERROR I clicked on G
The value of set is 0 for PID: 53446
SELECT * FROM atlantic_rr WHERE dept REGEXP '^F' ORDER BY dept, pay_list

This last entry for PID 53446 confirms my suspicion that for
some reason the CGI.pm query object and thus param('var') is not new on
every run. Why, I have no idea.

BTW, when you and Michael talk about logging via [warn] are you
reffering to a syslog change or some Perl function?

Thanks.

Brian

-----Original Message-----
From: Dondi Stroma [mailto:dstroma@verizon.net]
Sent: Friday, June 13, 2008 4:38 PM
To: Brian Gaber
Cc: modperl@perl.apache.org
Subject: Re: CGI.pm param and mod_perl

Brian Gaber wrote:

> The HTML code that I am selecting looks like this:

That's not necessary. What does your perl code look like now? Also, try
printing/warning the value of $$, which is the process ID. I think
you'll find that the value of your variable stays the same for each
process.

RE: CGI.pm param and mod_perl

am 13.06.2008 22:56:45 von Brian Gaber

Here are relevant parts of code:

use CGI '-autoload';
use DBI();
use warnings;
use strict;

# Initial declaration and/or population of global script variables

use vars qw($q);

$q =3D CGI->new();

open(DEBUGLOG, ">> /tmp/mod_perl_debug.txt");
foreach my $name ( $q->param() ) {
my $value =3D $q->param($name);
print DEBUGLOG "The value of $name is $value for PID: $$\n";
}=20

&print_form();

sub print_form {
my $region =3D $q->param('region');
my $dept2show =3D 'A';

if ( $q->param('deptLtr') ) {
($dept2show) =3D $q->param('deptLtr') =3D~ /^([a-zA-Z]{1})$/;
}

-----Original Message-----
From: Dondi Stroma [mailto:dstroma@verizon.net]=20
Sent: Friday, June 13, 2008 4:38 PM
To: Brian Gaber
Cc: modperl@perl.apache.org
Subject: Re: CGI.pm param and mod_perl

Brian Gaber wrote:

> The HTML code that I am selecting looks like this:

That's not necessary. What does your perl code look like now? Also, try
printing/warning the value of $$, which is the process ID. I think
you'll find that the value of your variable stays the same for each
process.=20

Re: CGI.pm param and mod_perl

am 13.06.2008 23:17:58 von Perrin Harkins

On Fri, Jun 13, 2008 at 2:53 PM, Michael Peters wrote:
> Doing a "$q = new CGI" means that you will get a new CGI object on every
> request, which is what you want. I've never used the function interface of
> CGI.pm like you did in your example so I don't know how CGI.pm handles it behind
> the scenes (whether it creates a new object on each request or not).

Sad to say, CGI->new is mostly just lipstick on a pig. Behind the
scenes, it still puts everything in globals. CGI.pm is just not an OO
module.

However, it is safe to use with mod_perl because it reinitializes the
globals on each request. The only problems I've run into with this
are from internal redirects, when it doesn't realize there's a fresh
request.

- Perrin