简体   繁体   中英

Perl CGI gets parameters from a different request to the current URL

This is a weird one. :)

I have a script running under Apache 1.3, with Apache::PerlRun option of mod_perl. It uses the standard CGI.pm module. It's a regularly accessed script on a busy server, accessed over https.

The URL is typically something like...

/script.pl?action=edit&id=47049

Which is then brought into Perl the usual way...

my $action = $cgi->param("action");
my $id = $cgi->param("id");

This has been working successfully for a couple of years. However we started getting support requests this week from our customers who were accessing this script and getting blank pages. We already had a line like the following that put the current URL into a form we use for customers to report an issue about a page...

$cgi->url(-query => 1);

And when we view source of the page, the result of that command is the same URL, but with an entirely different query string.

/script.pl?action=login&user=foo&password=bar

A query string that we recognise as being from a totally different script elsewhere on our system.

However crazy it sounds, it seems that when users are accessing a URL with a query string, the query string that the script is seeing is one from a previous request on another script. Of course the script can't handle that action and outputs nothing.

We have some automated test scripts running to see how often this happens, and it's not every time. To throw some extra confusion into the mix, after an Apache restart, the problem seems to initially disappear completely only to come back later. So whatever is causing it is somehow relieved by a restart, but we can't see how Apache can possibly take the request from one user and mix it up with another.

This, it appears, is an interesting combination of Apache 1.3, mod_perl 1.31, CGI.pm and Apache::GTopLimit.

A bug was logged against CGI.pm in May last year: RT #57184

Which also references CGI.pm params not being cleared?

CGI.pm registers a cleanup handler in order to cleanup all of it's cache.... (line 360)

$r->register_cleanup(\&CGI::_reset_globals);

Apache::GTopLimit (like Apache::SizeLimit mentioned in the bug report) also has a handler like this:

$r->post_connection(\&exit_if_too_big) if $r->is_main;

In pre mod_perl 1.31, post_connection and register_cleanup appears to push onto the stack, while in 1.31 it appears as if the GTopLimit one clobbers the CGI.pm entry. So if your GTopLimit function fires because the Apache process has got to large, then CGI.pm won't be cleaned up, leaving it open to returning the same parameters the next time you use it.

The solution seems to be to change line 360 of CGI.pm to;

$r->push_handlers( 'PerlCleanupHandler', \&CGI::_reset_globals);

Which explicitly pushes the handler onto the list.

Our restart of Apache temporarily resolved the problem because it reduced the size of all the processes and gave GTopLimit no reason to fire.

And we assume it has appeared over the past few weeks because we have increased the size of the Apache process either through new developments which included something that wasn't before.

All tests so far point to this being the issue, so fingers crossed it is!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM