Web Developer's Virtual Library: Encyclopedia of Web Design Tutorials, Articles and Discussions


WDVL Newsletter

Active Server Pages
JSP/Java Servlets
Microsoft SQL Server
Daily Backup
Dedicated Servers
Streaming Audio/Video
24-hour Support    

jobs.webdeveloper.com

Hiermenus


e-commerce
Partner With Us















Developer Channel
FlashKit.com
JavaScript.com
JavaScriptSource
Developer Jobs
ScriptSearch
StreamingMediaWorld
Web Developer's Journal
Web Developer's Virtual Library
WebDeveloper.com
Webreference
Web Hosts
XMLfiles.com

internet.com
IT
Developer
Internet News
Small Business
Personal Technology

Search internet.com
Advertise
Corporate Info
Newsletters
Tech Jobs
E-mail Offers


My() Troubles

May 15, 2000

First, some ground rules. When developing and testing your Perl scripts under mod_perl, there are some conditions you should set forth which will greatly help you to create properly functional code. To wit:

  1. Always "use strict" in your Perl code. This rule will force you to obey certain coding practices which are necessary under the mod_perl environment, such as how you scope variables. We'll see more on this momentarily.

  2. Enable the warning switch in your Perl script header, such as #!/usr/bin/perl -w. These warnings will be output to your Apache server's errorlog and can help you debug and track down mysterious problems. Do remember however to remove the warning switch once your code goes live, especially if your script does produce harmless warnings, or else your errorlog may grow faster than Louie Anderson at a state fair.

  3. Run your Apache server in "single process mode". Do this with the commandline httpd -X, or wherever the appropriate path to your Apache httpd is. In this mode, Apache will not spawn any children. One of the most common problems of mod_perl development is that sometimes Apache children will "remember" values from a previous invocation of a script, caused by the optimized nature of mod_perl and improperly coded scripts. Often this problem is masked when you test as a single user because new Apache children are spawned, thus failing to guarantee that your repeated tests are handled by a single child process. Confirming your scripts in a single Apache process will provide peace of mind that there are no hidden problems being obscured by the presence of multiple Apache children.

All that said, let's look at a sample mod_perl script which suffers from a mysterious ailment.

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

use CGI; 

my $cgiobj=new CGI; 

print $cgiobj->header; 

my $name=$cgiobj->param("firstname").' '.
   $cgiobj->param("lastname");

print &formatName($name); 

       

sub formatName { 

 return uc($name); 

} 

We run this script through the browser, by passing a URL to it with some parameters; e.g.
http://my.host/cgi-bin/welcome.cgi?firstname=martin&lastname=mungbean

And so the web page displays:

MARTIN MUNGBEAN

Notice that the one simple function of this script is to output the supplied name in all uppercase, via the uc() function.

Keeping in mind that Apache is running in single process mode (-X), we run the script again through the web browser, this time with the parameters firstname=jane&lastname=frowny. And so the web page displays:

MARTIN MUNGBEAN

No, that's not a typo on our part. The script seemed to ignore Jane Frowny. Yet, if we went and tried to execute this script from the command line rather than through the web browser (i.e. mod_perl) and supplied the appropriate parameters, it would output the correct name each time. So what's wrong with mod_perl? Nothing -- the question is, what is wrong with this script?

Ideally, we were hoping to create $name as a global variable that any subroutine could access. Often times this is not recommended, but there are cases where it is realistic. But we can't just create a true global variable because this is disallowed by the strict rule, which we must use with mod_perl. So, we scope our variables using my(). You can see that we declared $name using my() in the outer code of this example, and then we attempt to reference $name from inside a subroutine. This type of reference will cause problems in Perl when we use nested subroutines -- that is, a subroutine within a subroutine. In fact, because we have the warning switch enabled for Perl, you can see in the Apache errorlog a warning about just this problem:

Variable "$name" will not stay shared at
/home/username/cgi-bin/test.cgi line 10.

From the looks of it, our example code does not use a nested subroutine -- so where's the problem? As we alluded to earlier, Perl scripts under mod_perl do not run inside the main package; consequently, code that appears to be outside of any subroutines in our script is actually nested, because our whole script is nested, in a manner of speaking, inside a mod_perl subroutine named handler. This causes us to suffer from the nested subroutine problem with my() variables -- and, as we've seen, the Apache child process "remembers" the parameter values supplied on first invocation, and uses those precompiled values for each subsequent invocation. This is not good.

Solutions are good, and there are several. One solution, of course, is not to treat $name as a global variable, but rather to pass it in and out of any subroutines:

    
print &formatName($name); 

       

sub formatName { 

 my ($name)=@_;
 return uc($name); 

} 

This solution is advised where possible, but sometimes it is just not feasible to pass a variable around to every subroutine that uses it, especially when one subroutine does not need it but it needs to call another subroutine which does (it happens!). There's a better way.

The Perl You Need to Know Special: Introduction to mod_perl Part 2
The Perl You Need to Know
Repackage Your Way to Success


Up to => Home / Authoring / Languages / Perl / PerlfortheWeb




Jupiter Online Media: internet.comearthweb.comDevx.commediabistro.comGraphics.com

Search:

Jupitermedia Corporation has two divisions: Jupiterimages and Jupiter Online Media

Jupitermedia Corporate Info


Legal Notices, Licensing, & Permissions, Privacy Policy.

Web Hosting | Newsletters | Tech Jobs | Shopping | E-mail Offers