mod_perl_traps - common/known mod_perl traps


DESCRIPTION

       In the CGI environment, the server starts a single exter­
       nal process (Perl interpreter) per HTTP request which runs
       single script in that process space.  When the request is
       over, the process goes away everything is cleaned up and a
       fresh script is started for the next request.  mod_perl
       brings Perl inside of the HTTP server not only for speedup
       of CGI scripts, but also for access to server functional­
       ity that CGI scripts do not and/or cannot have.  Now that
       we're inside the server, each process will likely handle
       more than one Perl script and keep it "compiled" in memory
       for longer than a single HTTP request.  This new location
       and longer lifetime of Perl execution brings with it some
       common traps.  This document is here to tell you what they
       are and how to prevent them.  The descriptions here are
       short, please consult the mod_perl FAQ for more detail.
       If you trip over something not documented here, please
       send a message to the mod_perl list.

       Migrating from CGI

       ·   Be sure to have read the cgi_to_mod_perl manpage

       ·   Scripts under Apache::Registry are not run in package
           main, they are run in a unique namespace based on the
           requested uri.

       ·   Apache::Registry scripts cannot contain  __END__ or
           __DATA__ tokens

       ·   Output of `system', `exec' and `open PIPE, "|program"'
           calls will not be sent to the browser unless you Perl
           was configured with sfio.

       ·   Perl's exit() built-in function cannot be used in
           mod_perl scripts.  The Apache::exit() function should
           be used instead.  Apache::exit() automatically over­
           rides the built-in exit() for Apache::Registry and
           Apache::PerlRun scripts.

       ·   Your script *will not* run from the command line if
           your script makes any direct calls to Apache->methods.
           See Apache::FakeRequest.

       Apache::Registry

       undefined subroutine &Apache::Registry::handler
           Interaction with certain modules causes the shortcut
           configuration to break, if you see this message change


            <Location /perl>
            PerlHandler Apache::Registry
            ...
            </Location>

           To this:

            PerlModule Apache::Registry
            <Location /perl>
            PerlHandler Apache::Registry::handler
            ...
            </Location>

       Using CGI.pm and CGI::*

       ·   CGI.pm users must have version 2.39 of the package or
           higher, earlier versions will not work under mod_perl.

       ·   If you use the `SendHeaders()' function, be sure to
           call $req_obj->cgi->done when you are done with a
           request, just as you would under CGI::MiniSrv.

       Perl Modules and Extensions

       ·   Files pulled in via `use' or `require' statements are
           not automatically reloaded when changed on disk.  See
           the Apache::StatINC module to add this functionality.

       Undefined subroutines
           A common trap with required files may result in an
           error message similar to this in the error_log:

            [Thu Sep 11 11:03:06 1997] Undefined subroutine
            &Apache::ROOT::perl::test_2epl::some_function called at
            /opt/www/apache/perl/test.pl line 79.

           As the above items explains, a file pulled in via
           `require' will only happen once per-process (unless
           %INC is modified).  If the file does not contain a
           `package' declaration, the file's subroutines and
           variables will be created in the current package.
           Under CGI, this is commonly package `main'.  However,
           Apache::Registry scripts are compiled into a unique
           package name (base on the uri).  So, if multiple
           scripts in the same process try to require the same
           file, which does not declare a package, only one
           script will actually be able to see the subroutines.
           The solution is to read the perlmodlib manpage, the
           perlmod manpage and related perl documentation and re-

           functions or defines a method interface.  Or something
           more simple, along these lines:

            #required_file.pl
            package Test;

            sub some_function {...}

            ...

            __END__

           Now, have your scripts say:

            require "required_file.pl";

            Test::some_function();

       ""Use of uninitialized value""
           Because of eval context, you may see warnings with
           useless filename/line, example:

            Use of uninitialized value at (eval 80) line 12.
            Use of uninitialized value at (eval 80) line 43.
            Use of uninitialized value at (eval 80) line 44.

           To track down where this eval is really happening, try
           using a __WARN__ handler to give you a stack trace:

            use Carp ();
            local $SIG{__WARN__} = \&Carp::cluck;

       ""Callback called exit""

       ""Out of memory!""
           If something goes really wrong with your code, Perl
           may die with an "Out of memory!" message and or "Call­
           back called exit".  A common cause of this are never-
           ending loops, deep recursion or calling an undefined
           subroutine.  Here's one way to catch the problem: See
           Perl's INSTALL document for this item:

       -DPERL_EMERGENCY_SBRK
           If PERL_EMERGENCY_SBRK is defined, running out of mem­
           ory need not be a fatal error: a memory pool can allo­
           cated by assigning to the special variable $^M.  See
           perlvar(1) for more details.

           If you compile with that option and add 'use
           Apache::Debug level => 4;' to your PerlScript, it will
           allocate the $^M emergency pool and the $SIG{__DIE__}

           trace which should reveal where the problem is.

           See the Apache::Resource module for prevention of
           spinning httpds.

       ·   If you wish to use a module that is normally linked
           static with your Perl, it must be listed in static_ext
           in Perl's Config.pm to be linked with httpd during the
           mod_perl build.

       Can't load '$Config{sitearchexp}/auto/Foo/Foo.so' for mod­
           ule Foo...
           When starting httpd some people have reported seeing
           an error along the lines of:

            [Thu Jul  9 17:33:42 1998] [error] Can't load
            '/usr/local/ap/lib/perl5/site_perl/sun4-solaris/auto/DBI/DBI.so' for
            module DBI: ld.so.1: src/httpd: fatal: relocation error: file
            /usr/local/ap/lib/perl5/site_perl/sun4-solaris/auto/DBI/DBI.so: symbol
            Perl_sv_undef: referenced symbol not found at
            /usr/local/ap/lib/perl5/sun4-solaris/5.00404/DynaLoader.pm line 166.

           Or similar for the IO module or whatever dynamic mod­
           ule mod_perl tries to pull in first.  The solution is
           to re-configure, re-build and re-install Perl and
           dynamic modules with the following flags when Config­
           ure asks for "additional LD flags":

            -Xlinker --export-dynamic

           or

            -Xlinker -E

           This problem is only known to be caused by installing
           gnu ld under Solaris.

           Other known causes of this problem:

           OS distributions that ship with a (broken) binary Perl
           installation.

           The `perl' program and `libperl.a' library are somehow
           built with different binary compatiblity flags.

           The solution to these problems is to rebuild Perl and
           extension modules from a fresh source tree.  Tip for
           running Perl's Configure script, use the ``-des''
           flags to accepts defaults and ``-D'' flag to override
           certain attributes:

            % ./Configure -des -Dcc=gcc ... && make test && make install


       Clashes with other Apache C modules

       mod_auth_dbm
           If you are a user of mod_auth_dbm or mod_auth_db, you
           may need to edit Perl's `Config' module.  When Perl is
           configured it attempts to find libraries for ndbm,
           gdbm, db, etc., for the *DBM*_File modules.  By
           default, these libraries are linked with Perl and
           remembered by the Config module.  When mod_perl is
           configured with apache, the ExtUtils::Embed module
           returns these libraries to be linked with httpd so
           Perl extensions will work under mod_perl.  However,
           the order in which these libraries are stored in Con­
           fig.pm, may confuse `mod_auth_db*'.  If `mod_auth_db*'
           does not work with mod_perl, take a look at this order
           with the following command:

            % perl -V:libs

           If `-lgdbm' or `-ldb' is before `-lndbm', example:

            libs='-lnet -lnsl_s -lgdbm -lndbm -ldb -ldld -lm -lc -lndir -lcrypt';

           Edit Config.pm and move `-lgdbm' and `-ldb' to the end
           of the list.  Here's how to find Config.pm:

            % perl -MConfig -e 'print "$Config{archlibexp}/Config.pm\n"'

           Another solution for building
           Apache/mod_perl+mod_auth_dbm under Solaris is to
           remove the DBM and NDBM "emulation" from libgdbm.a.
           Seems Solaris already provides its own DBM and NDBM,
           and there's no reason to build GDBM with them (for us
           anyway).

           In our Makefile for GDBM, we changed

             OBJS = $(DBM_OF) $(NDBM_OF) $(GDBM_OF)

           to

             OBJS = $(GDBM_OF)

           Rebuild libgdbm, then Apache/mod_perl.


REGULAR EXPRESSIONS

       COMPILED REGULAR EXPRESSIONS

       When using a regular expression that contains an interpo­
       lated Perl variable, if it is known that the variable (or
       variables) will not vary during the execution of the

       adding the `o' modifier to the regexp pattern, to direct
       the compiler to build the internal table once, for the
       entire lifetime of the script, rather than every time the
       pattern is executed. Consider:

               my $pat = '^foo$'; # likely to be input from an HTML form field
               foreach( @list ) {
                       print if /$pat/o;
               }

       This is usually a big win in loops over lists, or when
       using `grep' or `map'.

       In long-lived `mod_perl' scripts, however, this can pose a
       problem if the variable changes according to the invoca­
       tion. The first invocation of a fresh httpd child will
       compile the table and perform the search correctly, how­
       ever, all subsequent uses by the httpd child will continue
       to match the original pattern, regardless of the current
       contents of the Perl variables the pattern is dependent
       on. Your script will appear broken.

       There are two solutions to this problem.

       The first is to use `eval q//', to force the code to be
       evaluated each time. Just make sure that the `eval' block
       covers the entire loop of processing, and not just the
       pattern match itself.

       The above code fragment would be rewritten as:

               my $pat = '^foo$';
               eval q{
                       foreach( @list ) {
                               print if /$pat/o;
                       }
               }

       Just saying

               eval q{ print if /$pat/o; };

       is going to be a horribly expensive proposition.

       You use this approach if you require more than one pattern
       match operator in a given section of code. If the section
       contains only one operator (be it an `m//' or `s///'), you
       can rely on the property of the null pattern, that reuses
       the last pattern seen. This leads to the second solution,
       which also eliminates the use of `eval'.

       The above code fragment becomes:

               "something" =~ /$pat/; # dummy match (MUST NOT FAIL!)
               foreach( @list ) {
                       print if //;
               }

       The only gotcha is that the dummy match that boots the
       regular expression engine must absolutely, positively suc­
       ceed, otherwise the pattern will not be cached, and the //
       will match everything. If you can't count on fixed text to
       ensure the match succeeds, you have two possibilities.

       If you can guaranteee that the pattern variable contains
       no meta-characters (things like `*', `+', `^', `$'...),
       you can use the dummy match:

               "$pat" =~ /\Q$pat\E/; # guaranteed if no meta-characters present

       If there is a possibility that the pattern can contain
       meta-characters, you should search for the pattern or the
       unsearchable `\377' character as follows:

               "\377" =~ /$pat|^[\377]$/; # guarenteed if meta-characters present

       References

               The Camel Book, 2nd edition, p. 538 (p. 356 in the 1st edition).


AUTHORS

       Doug MacEachern, with contributions from Jens Heunemann
       <heunemann2@janet.de>, David Landgren <david@land­
       gren.net>, Mark Mills <mark@ntr.net> and Randal Schwartz
       <merlyn@stonehenge.com>


Man(1) output converted with man2html