You are viewing a plain text version of this content. The canonical link for it is here.
Posted to modperl@perl.apache.org by Jim Albert <ji...@netrition.com> on 2005/10/04 19:22:09 UTC
ModPerl::PerlRun CGI.pm SSI
I'm trying to debug a strange situation with the following environment:
Apache 2.0.54
mod_perl 2.0.1
perl 5.8.6
CGI.pm 3.10
Linux 2.6.12-1.1447_FC4smp
Say I have a mod_perl script called x.cgi configured for mod_perl as
follows:
<Location /cgi/x.cgi>
SetHandler perl-script
PerlHandler ModPerl::PerlRun
Options ExecCGI
PerlSendHeader On
</Location>
**NOTE that I am using ModPerl::PerlRun
x.cgi uses CGI.pm as follows:
----
use strict;
use CGI qw (:cgi);
my $inp = param('inp');
print STDERR ("inp = $inp\n");
----
x.cgi works fine as a ModPerl::PerlRun script except for the case where
I use it multiple times as a Server Side Include in the same .html file
as follows:
<HTML><HEAD></HEAD>
<BODY>
<!--#include virtual="/cgi/x.cgi?inp=50"-->
<P>
<!--#include virtual="/cgi/x.cgi?inp=51"-->
</BODY>
</HTML>
In such a case the value of inp prints as 50 for both calls.
I've tested this on a single httpd process system and x.cgi works
properly for multiple calls to it (with different values for inp) during
the life of that single httpd process. I only get the strange incorrect
results when used as a server side include multiple times within the
same html file.
After attempting to track down the problem, the best I can come up with
is there is a global @QUERY_PARAM array in CGI.pm that does not get
cleared when x.cgi is uses multiple times as server side include in the
same html file. If @QUERY_PARAM is not cleared, CGI.pm continues to use
the same QUERY_STRING.
However, I don't believe this is a CGI.pm bug. I believe
ModPerl::PerlRun appears to be clearing @QUERY_PARAM properly between
multiple calls of x.cgi. However, ModPerl::PerlRun does not appear to
clearing @QUERY_PARAM between multiple calls to x.cgi when x.cgi is used
mutliple times as a server side include in the same html file.
I'm guessing there is either a problem with ModPerl::PerlRun or Apache
2.0.54.
Perhaps there is some httpd.conf or perl.conf configuration I should be
looking at?
Thanks for any help you can provide as currently the only solution I
have is to hack up CGI.pm but I don't believe that is the best solution
as the relevant code of CGI.pm does not appear to have changed from
another version of CGI.pm on a different system where this works fine.
--
Jim Albert
Re: ModPerl::PerlRun CGI.pm SSI
Posted by Perrin Harkins <pe...@elem.com>.
Jim Albert wrote:
> Lack of response on this tells me:
>
> 1. Nobody is using ModPerl::PerlRun any longer to run their scripts
> under mod_perl. I doubt it.
Hopefully most people use Registry instead, but it has the same issue
with CGI.pm and subrequests.
> 2. There is an alternative to CGI.pm that is mod_perl safe. If there is
> a mod_perl safe alternative to CGI.pm for use under ModPerl::PerlRun
> scripts for things like retrieving input from QUERY_STRING and working
> with cookies, please point me to what you use for this.
Pretty much all of the CGI.pm alternatives should work. That includes
libapreq, as well as things like CGI::Simple and the other "light"
alternatives on CPAN.
If you want to stick with CGI.pm, the solution you came up with is the
correct one.
- Perrin
Re: ModPerl::PerlRun CGI.pm SSI
Posted by Jim Albert <ji...@netrition.com>.
Perrin Harkins wrote:
> On Thu, 2005-10-06 at 11:53 -0400, Jim Albert wrote:
>
>>Besides the fact that if I choose
>>the scripts to run mod_cgi perhaps in a non mod_perl environment,
>>then
>>they are all set to go.
>
>
> This is true with Registry scripts as well.
>
>
>>I thought this was safer than calling CGI::initiliaze_globals
>
>
> I don't think it is. Guessing at which ones need to be cleared sounds
> less safe to me.
>
> I have successfully used the CGI::initialize_globals workaround when
> needing to support CGI.pm with subrequests, and I recommend that you use
> it if you want to stick with CGI.pm.
Yes, I agree. Especially since I had to move to using CGI.pm via OO
anyway so any changes that CGI.pm makes to those globals just happen
again after me clearing the globals when i I call the CGI::new() method.
I had previously thought best otherwise when I thought I could continue
to use CGI.pm non-OO.
Thanks for bringing that to mind.
>
> Ultimately, you're better off abandoning CGI.pm for something else.
> There are alternatives with an identical API if all you need is
> parameter parsing.
OK, thanks... I'll check some of them out when I have some more time.
Right now, CGI::initiliaze_globals is the quickest way for me to get my
problem resolved.
Thanks all for confirming my thoughts on this problem.
--
Jim Albert
Re: ModPerl::PerlRun CGI.pm SSI
Posted by Perrin Harkins <pe...@elem.com>.
On Thu, 2005-10-06 at 11:53 -0400, Jim Albert wrote:
> Besides the fact that if I choose
> the scripts to run mod_cgi perhaps in a non mod_perl environment,
> then
> they are all set to go.
This is true with Registry scripts as well.
> I thought this was safer than calling CGI::initiliaze_globals
I don't think it is. Guessing at which ones need to be cleared sounds
less safe to me.
I have successfully used the CGI::initialize_globals workaround when
needing to support CGI.pm with subrequests, and I recommend that you use
it if you want to stick with CGI.pm.
Ultimately, you're better off abandoning CGI.pm for something else.
There are alternatives with an identical API if all you need is
parameter parsing.
- Perrin
Re: ModPerl::PerlRun CGI.pm SSI
Posted by Jim Albert <ji...@netrition.com>.
Michael Peters wrote:
>
> Jim Albert wrote:
>
>>Lack of response on this tells me:
>>
>>1. Nobody is using ModPerl::PerlRun any longer to run their scripts
>>under mod_perl. I doubt it.
>
>
>>>From the docs:
> This module is meant for "Dirty" CGI Perl scripts
>
> and
>
> The Apache::Registry handler is much faster
>
> So new development shouldn't be targetting PerlRun anymore, but
> Registry. If you are trying to work with a legacy app, then that is more
> understandable.
Yes, I have a lot of old code and I don't ever see myself having enough
time to convert it to Registry, if that would in fact be better for my
situation. I've never really agreed with the "dirty" cgi perl scripts
terminology. I really consider PerlRun and Registry simply different
paradigms. With PerlRun my script itself doesn't get loaded persistently
into memory, but that's not a huge deal... perl and all the modules the
script uses do get loaded persistently so that probably accounts for 90%
of the speedup since most of my code is in underlying modules which are
mod_perl safe. To convert them to Registry to gain maybe another 10%
doesn't seem to be worth the effort. Besides the fact that if I choose
the scripts to run mod_cgi perhaps in a non mod_perl environment, then
they are all set to go. My code does run under various apache
environments so keeping it flexible is important to me.
Hopefully future mod_perl versions don't discount what I would guess is
the large amount of PerlRun code still running out there. If people have
code and it works, most don't have time to write it over to make it work
in a different way.
>
>
>>2. There is an alternative to CGI.pm that is mod_perl safe. If there is
>>a mod_perl safe alternative to CGI.pm for use under ModPerl::PerlRun
>>scripts for things like retrieving input from QUERY_STRING and working
>>with cookies, please point me to what you use for this.
>
>
> Have you tried using CGI.pm in an OO fashion to see if it fixes the
> problem you're having? If that doesn't work, then I'd suggest sticking
> with your original thought and just do the resetting the globals
> yourself at the beginning of every request.
>
> CGI::_reset_globals();
Actually, you're partly correct. I'm sorry... I forgot to point that out
in my previous messages. I actually did have to switch to using CGI.pm
in OO via something like:
my $cgi_obj = CGI->new();
I needed to switch to this in order to have the new() method called for
each run of my cgi in the request since it is new() that calls init()
which is what reads in the request information.
However, simply switching to OO was not enough. That didn't clear out
the global variables in CGI.pm such as @QUERY_PARAM between calls to my
cgi. I wrote a method in one of my modules named NetrCGI.pm to do the
following:
sub NetrCGI_makeCGIdotPMmodPerlSafe
{
my $self = shift;
undef @CGI::QUERY_PARAM;
undef $CGI::QUERY_CHARSET;
undef %CGI::QUERY_FIELDNAMES;
}
I thought this was safer than calling CGI::initiliaze_globals since I
wasn't sure if the values of all those globals were important throughout
the use of CGI.pm, but I convinced myself that I could safely undef the
above three variables since they only seem to be used for saving state
which was the problem for me to begin with. Actually, undefing
@QUERY_PARAM would have been sufficient for my problem.
>
> I don't think your scenario is common enough to get this put into CGI.pm
> itself since it would slow down everyone else (which is why Lincoln put
> it into a cleanup handler in the first place, so it's run after the
> output has been sent to the browser).
Yes, and in most cases that's fine, except for (at least) the case where
the httpd process is running multiple mod_perled scripts in a single
request... for example, mutiple server side includes of the script in
the same html file.
>
> But you may be able to convince Lincoln to make the method public and
> documented so that it won't get ripped out from under you some day.
Yes, I was thinking maybe an option to the new() method to force an
immediate call to initialize_globals seems like maybe a good way to do
it. Then anyone not affected by this can simply ignore it. But, I'd
leave that open for Lincoln to decide how best to put in the hook so as
to have no impact on those not affected by this. It does look Lincoln
made an effort to keep CGI.pm mod_perl safe, so hopefully he can add in
this extra hook to keep it more mod_perl safe. I've forwarded him these
suggestions.
Alternatively, I was considering just turning on $CGI::PERLEX since this
forces a call to _reset_globals in new. However, I see this that
$CGI::PERLEX is meant to indicate ActivateState's PerlEx. I don't know
what that is or what it might indicate in future versions of CGI.pm so I
chose against turning that variable on.
# Turn on special checking for ActiveState's PerlEx
$PERLEX++ if defined($ENV{'GATEWAY_INTERFACE'}) &&
$ENV{'GATEWAY_INTERFACE'} =~ /^CGI-PerlEx/;
The hook into new() to force a _refresh_globals seems cleanest but
another global like $CGI::PERLEX that is not tied to ActiveState's
PerlEx would also work.
--
Jim Albert
Re: ModPerl::PerlRun CGI.pm SSI
Posted by Michael Peters <mp...@plusthree.com>.
Jim Albert wrote:
> Lack of response on this tells me:
>
> 1. Nobody is using ModPerl::PerlRun any longer to run their scripts
> under mod_perl. I doubt it.
>From the docs:
This module is meant for "Dirty" CGI Perl scripts
and
The Apache::Registry handler is much faster
So new development shouldn't be targetting PerlRun anymore, but
Registry. If you are trying to work with a legacy app, then that is more
understandable.
> 2. There is an alternative to CGI.pm that is mod_perl safe. If there is
> a mod_perl safe alternative to CGI.pm for use under ModPerl::PerlRun
> scripts for things like retrieving input from QUERY_STRING and working
> with cookies, please point me to what you use for this.
Have you tried using CGI.pm in an OO fashion to see if it fixes the
problem you're having? If that doesn't work, then I'd suggest sticking
with your original thought and just do the resetting the globals
yourself at the beginning of every request.
CGI::_reset_globals();
I don't think your scenario is common enough to get this put into CGI.pm
itself since it would slow down everyone else (which is why Lincoln put
it into a cleanup handler in the first place, so it's run after the
output has been sent to the browser).
But you may be able to convince Lincoln to make the method public and
documented so that it won't get ripped out from under you some day.
--
Michael Peters
Developer
Plus Three, LP
Re: ModPerl::PerlRun CGI.pm SSI
Posted by Jim Albert <ji...@netrition.com>.
Lack of response on this tells me:
1. Nobody is using ModPerl::PerlRun any longer to run their scripts
under mod_perl. I doubt it.
2. There is an alternative to CGI.pm that is mod_perl safe. If there is
a mod_perl safe alternative to CGI.pm for use under ModPerl::PerlRun
scripts for things like retrieving input from QUERY_STRING and working
with cookies, please point me to what you use for this.
Thanks.
Jim Albert wrote:
> I think I may now have a better understanding of this and that the
> problem lies in CGI.pm. I've emailed the following to Lincoln Stein
> explaining what I believe to be true. Perhaps someone can either confirm
> my understanding or otherwise correct me.
>
> My email to Lincoln Stein is as follows:
> I did some more research and I believe I understand the problem and why
> it only happens when the mod_perled x.cgi is used multiple times as a
> server side include within the same html file.
>
> The issue is with this line of code in CGI::new
> $r->pool->cleanup_register(\&CGI::_reset_globals);
>
> From my understanding, that sets up a apache callback to clean up your
> globals **after** the apache process is done serving the request.
>
> However, in the case where x.cgi is used multiple times as a server side
> include in the same html file, _reset_globals is not called until the
> apache process is done with the request.
>
> It seems to me it would be best simply to call _reset_globals first
> thing in your new() method when you detect a mod_perl environment. That
> way we know all those globals are clean for each use.
>
> Unless you can offer another suggestion, my solution at present is to
> add the following to all my mod_perled scripts that use CGI.pm:
> CGI::initialize_globals();
>
> I hope you can help with this.
>
> Jim Albert wrote:
>
>> I'm trying to debug a strange situation with the following environment:
>> Apache 2.0.54
>> mod_perl 2.0.1
>> perl 5.8.6
>> CGI.pm 3.10
>> Linux 2.6.12-1.1447_FC4smp
>>
>> Say I have a mod_perl script called x.cgi configured for mod_perl as
>> follows:
>> <Location /cgi/x.cgi>
>> SetHandler perl-script
>> PerlHandler ModPerl::PerlRun
>> Options ExecCGI
>> PerlSendHeader On
>> </Location>
>>
>> **NOTE that I am using ModPerl::PerlRun
>>
>> x.cgi uses CGI.pm as follows:
>> ----
>> use strict;
>> use CGI qw (:cgi);
>>
>> my $inp = param('inp');
>> print STDERR ("inp = $inp\n");
>> ----
>>
>> x.cgi works fine as a ModPerl::PerlRun script except for the case
>> where I use it multiple times as a Server Side Include in the same
>> .html file as follows:
>>
>> <HTML><HEAD></HEAD>
>> <BODY>
>> <!--#include virtual="/cgi/x.cgi?inp=50"-->
>> <P>
>> <!--#include virtual="/cgi/x.cgi?inp=51"-->
>> </BODY>
>> </HTML>
>>
>> In such a case the value of inp prints as 50 for both calls.
>>
>> I've tested this on a single httpd process system and x.cgi works
>> properly for multiple calls to it (with different values for inp)
>> during the life of that single httpd process. I only get the strange
>> incorrect results when used as a server side include multiple times
>> within the same html file.
>>
>> After attempting to track down the problem, the best I can come up
>> with is there is a global @QUERY_PARAM array in CGI.pm that does not
>> get cleared when x.cgi is uses multiple times as server side include
>> in the same html file. If @QUERY_PARAM is not cleared, CGI.pm
>> continues to use the same QUERY_STRING.
>>
>> However, I don't believe this is a CGI.pm bug. I believe
>> ModPerl::PerlRun appears to be clearing @QUERY_PARAM properly between
>> multiple calls of x.cgi. However, ModPerl::PerlRun does not appear to
>> clearing @QUERY_PARAM between multiple calls to x.cgi when x.cgi is
>> used mutliple times as a server side include in the same html file.
>>
>> I'm guessing there is either a problem with ModPerl::PerlRun or Apache
>> 2.0.54.
>>
>> Perhaps there is some httpd.conf or perl.conf configuration I should
>> be looking at?
>>
>> Thanks for any help you can provide as currently the only solution I
>> have is to hack up CGI.pm but I don't believe that is the best
>> solution as the relevant code of CGI.pm does not appear to have
>> changed from another version of CGI.pm on a different system where
>> this works fine.
>>
>
>
--
Jim Albert
Re: ModPerl::PerlRun CGI.pm SSI
Posted by Jim Albert <ji...@netrition.com>.
I think I may now have a better understanding of this and that the
problem lies in CGI.pm. I've emailed the following to Lincoln Stein
explaining what I believe to be true. Perhaps someone can either confirm
my understanding or otherwise correct me.
My email to Lincoln Stein is as follows:
I did some more research and I believe I understand the problem and why
it only happens when the mod_perled x.cgi is used multiple times as a
server side include within the same html file.
The issue is with this line of code in CGI::new
$r->pool->cleanup_register(\&CGI::_reset_globals);
From my understanding, that sets up a apache callback to clean up your
globals **after** the apache process is done serving the request.
However, in the case where x.cgi is used multiple times as a server side
include in the same html file, _reset_globals is not called until the
apache process is done with the request.
It seems to me it would be best simply to call _reset_globals first
thing in your new() method when you detect a mod_perl environment. That
way we know all those globals are clean for each use.
Unless you can offer another suggestion, my solution at present is to
add the following to all my mod_perled scripts that use CGI.pm:
CGI::initialize_globals();
I hope you can help with this.
Jim Albert wrote:
> I'm trying to debug a strange situation with the following environment:
> Apache 2.0.54
> mod_perl 2.0.1
> perl 5.8.6
> CGI.pm 3.10
> Linux 2.6.12-1.1447_FC4smp
>
> Say I have a mod_perl script called x.cgi configured for mod_perl as
> follows:
> <Location /cgi/x.cgi>
> SetHandler perl-script
> PerlHandler ModPerl::PerlRun
> Options ExecCGI
> PerlSendHeader On
> </Location>
>
> **NOTE that I am using ModPerl::PerlRun
>
> x.cgi uses CGI.pm as follows:
> ----
> use strict;
> use CGI qw (:cgi);
>
> my $inp = param('inp');
> print STDERR ("inp = $inp\n");
> ----
>
> x.cgi works fine as a ModPerl::PerlRun script except for the case where
> I use it multiple times as a Server Side Include in the same .html file
> as follows:
>
> <HTML><HEAD></HEAD>
> <BODY>
> <!--#include virtual="/cgi/x.cgi?inp=50"-->
> <P>
> <!--#include virtual="/cgi/x.cgi?inp=51"-->
> </BODY>
> </HTML>
>
> In such a case the value of inp prints as 50 for both calls.
>
> I've tested this on a single httpd process system and x.cgi works
> properly for multiple calls to it (with different values for inp) during
> the life of that single httpd process. I only get the strange incorrect
> results when used as a server side include multiple times within the
> same html file.
>
> After attempting to track down the problem, the best I can come up with
> is there is a global @QUERY_PARAM array in CGI.pm that does not get
> cleared when x.cgi is uses multiple times as server side include in the
> same html file. If @QUERY_PARAM is not cleared, CGI.pm continues to use
> the same QUERY_STRING.
>
> However, I don't believe this is a CGI.pm bug. I believe
> ModPerl::PerlRun appears to be clearing @QUERY_PARAM properly between
> multiple calls of x.cgi. However, ModPerl::PerlRun does not appear to
> clearing @QUERY_PARAM between multiple calls to x.cgi when x.cgi is used
> mutliple times as a server side include in the same html file.
>
> I'm guessing there is either a problem with ModPerl::PerlRun or Apache
> 2.0.54.
>
> Perhaps there is some httpd.conf or perl.conf configuration I should be
> looking at?
>
> Thanks for any help you can provide as currently the only solution I
> have is to hack up CGI.pm but I don't believe that is the best solution
> as the relevant code of CGI.pm does not appear to have changed from
> another version of CGI.pm on a different system where this works fine.
>
--
Jim Albert