Coruscate has asked for the wisdom of the Perl Monks concerning the following question:

I recently installed Apache 2.0.48 and mod_perl 1.99.xx. I immediately went into producing small snippets to test out the mod_perl environment. Just as fast, I've come across certain issues I hope I can have addressed. They follow below.

One of the first things I wondered is how far a person can go in respect to loading everything into memory and executing as little code as possible on each server hit. First thing I did was throw a PerlModule Apache::DBI line into httpd.conf to pool database connections. Second, I tried a simple script that loads CGI::Simple and prints a simple document. I then tried one with file io and discovered a "glitch" I don't like. The following script introduces most of my questions:

#!c:/perl/bin/perl -w $|++; use strict; use Cwd; our $q; BEGIN { require CGI::Simple; $q = CGI::Simple->new; } print $q->header('text/plain'), "We're in ", cwd();

First question I have: will the $|++; carry over to each repeated request? Will output buffering be disabled upon each server hit? Second of all, note the way I initialized the CGI::Simple object. I don't think I gain anything by loading the module within a BEGIN block; a module is only compiled once, so a simple use CGI::Simple; at the top of the script should be just as good right? I keep the same object alive throughout the life of the interpreter. Will CGI::Simple DWIM and be safe to use in such a manner? Or should I revert to creating a new query object on each hit? It works with this simple script, but will it become fubar'ed in certain situations? Next comes the "glitch" with the cwd. Even though the script is c:/apache2/www/port80/serve, it is run from c:/apache2. Besides doing a chdir "c:/apache2/www/port80/serve"; at the top of each script, is there an easier way to fix this? Perhaps a directive within httpd.conf or perl.conf to do a chdir itself before executing the script?

Another question: If I start up apache/mod_perl, run one of the scripts, edit that script's source and then run it again, I see that apache notes the modified timestamp on the file and recompiles the script. My question is whether the older source is expunged from memory or if it is kept around even though it won't be used again.

Yet another question: As far as I've heard, ModPerl::Registry overrides perl's core exit() function, so that the interpreter is not actually exited. Is it still safe to use exit() as a "stop executing code here" way of thinking? How about die()? When die() is called, will the interpreter exit? Is it safe to use $SIG{__DIE__} to catch the errors to a logfile?

Hope to hear some good answers to these questions. If anyone has more information about common mod_perl pitfalls and/or links to good FAQs, please share!

Replies are listed 'Best First'.
Re: Knowing what works with mod_perl
by liz (Monsignor) on Dec 26, 2003 at 12:08 UTC
    I've always used mod_perl as lean and as mean as possible, so I can't tell you what CGI::xx or ModPerl::Registry does or doesn't do.

    However, I've found the mod_perl mailing list to be very responsive to questions. Maybe you could filter back some of the good answers to the Monastery?

    To answer one question I think I do know the answer to:

    ...ModPerl::Registry overrides perl's core exit() function, so that the interpreter is not actually exited. Is it still safe to use exit() as a "stop executing code here" way of thinking?

    That's why exit() was overwritten. So you can use exit() as a "stop executing code here". I've used a similar approach in Thread::Exit, which allows you to exit a thread rather than exiting the entire process, taking down all other threads with you.

    Hope this helps.

    Liz

Re: Knowing what works with mod_perl
by talexb (Chancellor) on Dec 26, 2003 at 04:31 UTC

    I think you don't need to worry about putting stuff in a BEGIN block as you've indicated -- I believe that mod_perl is clever enough to do what you want it to.

    If you edit something, an old version of the script might still be in memory. Years ago I would do an apachectl graceful to get Apache to pay attention to the change I'd just made. Sometimes that wouldn't work, and I'd have to rename the file, press refresh a couple dozen times until I got the "Unknown module" error, then restore the file and continue testing.

    I think you can still call exit as you're suggesting -- to stop execution of that instance of the code. But a test should be fairly easy to set up.

    I wish I could provide more information, but my experience comes from a period of frantic web development in 1998-2000, and some more recent 'dabbling' that has re-introduced me to mod_perl without actually giving me time to get really familiar with it.

    Good luck!

    --t. alex
    Life is short: get busy!
Re: Knowing what works with mod_perl
by Coruscate (Sexton) on Dec 26, 2003 at 03:49 UTC

    More questions! Is there a difference between using PerlModule Apache::DBI within httpd.conf and using use DBI; within startup.pl (run as PerlRequire "C:/Apache2/conf/startup.pl" within perl.conf)?

    Also, if anybody knows of an excellent resource for learning how to code more of a pure mod_perl script (using the Apache::xxx modules rather than using a module such as CGI::Simple). The sample script created at 'http://server.com/hello' is kind of boggling. Not to mention there is no POD for the modules this is supposidly coming from (Apache::RequestRec for example just does something with Apache::XSLoader). Very confusing for a beginner in the area.

      Is there a difference between using PerlModule Apache::DBI within httpd.conf and using use DBI; within startup.pl...

      No, I don't think so. You should realize that anything that mod_perl loads, is basically done at runtime with either a require or a string eval. This means that you can have BEGIN {} blocks (because you can have them in a string eval as well). END {} blocks are handled differently.

      ...Not to mention there is no POD for the modules...

      That still is indeed a problem. Patches are welcome. If there is a function with the same name in mod_perl 1.0, and it's not mentioned in the Porting document, you can assume that the API of the function is still the same.

      Hope this helps.

      Liz

      Update:
      Argh... Missed the "Apache::" versus non Apache in your question. Yes, definitely a difference: see bart's answer.

      Is there a difference between using PerlModule Apache::DBI within httpd.conf and using use DBI; within startup.pl (run as PerlRequire "C:/Apache2/conf/startup.pl" within perl.conf)?
      There should be. According to the docs of Apache::DBI, the latter serves to create a pool of permanent database connections, which means it changes the behaviour of DBI. OTOH, when just using DBI, without Apache::DBI, you still create a new connection every time a script runs — even though the module itself remains loaded.