Apache The Definitive Guide, 3rd EditionApache: The Definitive GuideSearch this book

17.5. Global Variables

The biggest single "gotcha" for scripts running under Apache::Registry is caused by global variables. The mod_cgi environment is rather kind to the slack programmer. Your scripts, which tend to be short and simple, get loaded, run, and then thrown away. Perl rather considerately initializes all variables to undef at startup, so one tends to forget about the dangers they represent.

Unhappily, under mod_perl and Apache::Registry, scripts effectively run as subroutines. Global variables get initialized at startup as usual, but not again, so if you don't explicitly initialize them at each call, they will carry forward whatever value they had after the last call. What makes these bugs more puzzling is that as the Apache child processes start, each one of them has its variables set to 0. The errant behavior will not begin to show until a child process is used a second time — and maybe not even then.

There are several lines of attack:

To illustrate this tiresome behavior we created a new directory /usr/www/APACHE3/APACHE3/site.mod_perl/mod_perl and copied everything across into it from.../mod_cgi. The startup file go was now:

httpd.perl -d /usr/www/APACHE3/APACHE3/site.mod_perl/mod_perl

The Config file is as follows:

User webuser
Group webuser
ServerName www.butterthlies.com
LogLevel debug

DocumentRoot /usr/www/APACHE3/APACHE3/site.mod_perl/mod_cgi/htdocs
TransferLog /usr/www/APACHE3/APACHE3/site.mod_perl/logs/access_log
ErrorLog /usr/www/APACHE3/APACHE3/site.mod_perl/logs/error_log
LogLevel debug

#change to AliasMatch from ScriptAliasMatch
AliasMatch /(.*) /usr/www/APACHE3/APACHE3/site.mod_perl/cgi-bin/$1

DirectoryIndex /bin/home

Alias /bin /usr/www/APACHE3/APACHE3/site.mod_perl/cgi-bin
SetHandler perl-script
PerlHandler Apache::Registry
#PerlHandler Apache::PerlRun

Notice that the convenient directives ScriptAlias and ScriptAliasMatch, which effectively encapsulate an Alias directive followed by SetHandler cgi-script for use under , are no longer available.

You have to declare an Alias, then that you are running perl-script, and then what flavor, or intensity of mod_perl you want.

The script home is now:

#! /usr/local/bin/perl -w
use strict;

print qq(content-type: text/html\n\n);

my $global=0;

    for(1 .. 5)
        {
        &inc_g( );
        }

print qq(<HTML><HEAD><TITLE>Demo CGI Home Page</TITLE></HEAD>
<BODY>Hi: I'm a demo home page. Global = $global<BR>
<A HREF="/AA_next">Click here to run my mate</A>
</BODY></HTML>);

sub inc_g( )
    {
    $global+=1;
    print qq(global = $global<BR>);
}

If you fire up Apache and watch the output, you don't have to reload it many times (having turned off caching in your browser, of course) before you see the following unnerving display:

content-type: text/html global = 21
global = 22
global = 23
global = 24
global = 25
Hi: I'm a demo home page. Global = 0
Click here to run my mate 

This unpleasant behavior is accompanied by the following message in the error_log file:

Variable "$global" will not stay shared at /usr/www/APACHE3/APACHE3/site.mod_perl/
cgi-bin/home

which should give you a pretty good warning that all is not well. If you start Apache up using the -X flag — to prevent child processes — then the bad behavior begins on the first reload.

It will not happen at all if you use the line:

PerlHandler Apache::PerlRun

because under PerlRun, although Perl itself stays loaded, your scripts are reloaded at each call — and, of course, all the variables are initialized. There is a performance penalty, of course.

17.5.1. Perl Flags

When your scripts ran under mod_cgi, they started off with the "shebang line":

#! usr/local/bin/perl -w -T

Under mod_perl this is no longer necessary. However, it is tolerated, so you don't have to remove it, and the -w flag is even picked up and invokes warnings. It would be too simple if all the other possible flags were also recognized, so if you use -T to invoke taint checking, it won't work. You have to use PerlTaintCheck On, PerlWarning On in the Apache Config file. It is recommended that you always use PerlTaintCheck to guard against attempts to hack your scripts by way of dubious entries in HTML forms. It is recommended that you have PerlWarn on while the scripts are being developed, but when in production to turn warnings off since one warning per visitor, written to the log file on a busy site, can soon use up all the available disk space and bring the server to a halt.



Library Navigation Links

Copyright © 2003 O'Reilly & Associates. All rights reserved.