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