Table of Contents:
The
Writing Apache Modules with Perl and C
book can be purchased online from O'Reilly
and
Amazon.com.
|
Your corrections of the technical and grammatical
errors are very welcome. You are encouraged to help me
improve this guide. If you have something to contribute
please send it
directly to me.
|
Perl's warnings mode is immensely helpful in detecting possible problems. Make sure you always turn on warnings while you are developing code. See The Importance of Warnings.
Enabling use diagnostics;
generally helps you to determine the source of the problem and how to solve
it. See diagnostics pragma for more information.
[ TOC ]
See make Troubleshooting and make test Troubleshooting
[ TOC ]
This section talks about errors reported when you attempt to start the server.
[ TOC ]
If when you run the server you get the following error:
libexec/libperl.so: open failed: No such file or directory |
it probably means that Perl was compiled with a shared library. mod_perl does detect this and links the Apache executable to the Perl shared library (libperl.so).
First of all make sure you have Perl installed on the machine, and that you have libperl.so in <perlroot>/<version>/<architecture>/CORE. For example in /usr/local/lib/perl5/5.00503/sun4-solaris/CORE.
Then make sure that that directory is included in the environment variable LD_LIBRARY_PRELOAD
. Under normal circumstances, Apache should have the path configured at
compile time, but this way you can override the library path.
[ TOC ]
install_driver(Oracle) failed: Can't load '/usr/lib/perl5/site_perl/5.005/i386-linux/auto/DBD/Oracle/Oracle.so' for module DBD::Oracle: libclntsh.so.8.0: cannot open shared object file: No such file or directory at /usr/lib/perl5/5.00503/i386-linux/DynaLoader.pm line 169. at (eval 27) line 3 Perhaps a required shared library or dll isn't installed where expected at /usr/local/apache/perl/tmp.pl line 11 |
On BSD style filesystems LD_LIBRARY_PATH
is not searched for setuid programs (a.k.a., Apache). This isn't a problem
for CGIs since they don't do a setuid (and are forked off), but Apache
does, and mod_perl is in Apache. Therefore the first solution is to
explicitly load the library from the system wide ldconfig configuration file:
# echo $ORACLE_HOME/lib >> /etc/ld.so.conf # ldconfig |
Another solution to this problem is to modify the resulting
Makefile ( after running perl Makefile.PL
) as follows:
1. search for the line LD_RUN_PATH=
2. replace it with LD_RUN_PATH=(my_oracle_home)/lib
(my_oracle_home) is, of course, the home path to your oracle installation. In particular, the file libclntsh.so.8.0 should exist in that directory. (If you use cpan, the build directory for DBD::Oracle should be in ~/.cpan/build/DBD-Oracle-1.06/ if you're logged in as root.)
Then, just type make install
, and all should go well.
FYI, setting LD_RUN_PATH
has the effect of hard-coding the path to
(my_oracle_home)/lib in the resulting Oracle.so
file generated by the DBD::Oracle
so that at run-time, it doesn't have to go searching through LD_LIBRARY_PATH
or the default directories used by ld
.
For more information see the ld manpage and an essay on
LD_LIBRARY_PATH
: http://www.visi.com/~barr/ldpath.html
[ TOC ]
Syntax error on line 393 of /etc/httpd/conf/httpd.conf: Invalid command 'PerlHandler', perhaps mis-spelled or defined by a module not included in the server configuration [FAILED] |
This can happen when you have a mod_perl enabled Apache compiled with DSO (generally it's an installed RPM or other binary package) but the mod_perl module isn't loaded. In this case you have to tell Apache to load mod_perl by adding:
AddModule mod_perl.c |
in your config file.
This can also happen when you try to run a non-mod_perl Apache server using the configuration from a mod_perl server.
[ TOC ]
RegistryLoader: Translation of uri [/home/httpd/perl/test.pl] to filename failed [tried: /home/httpd/docs/home/httpd/perl/test.pl] |
This warning shows up when RegistryLoader
fails to translate the URI into the corresponding filesystem path. Most
failures happen when one passes a file path instead of URI. (A reminder:
/home/httpd/perl/test.pl is a file path, while /perl/test.pl is a URI). In most cases all you have to do is to pass something that
RegistryLoader
expects to get - the URI, but there are more complex cases. RegistryLoader
's man page shows how to handle these cases as well (look for the
trans()
sub).
[ TOC ]
If your server startup fails with:
Apache.pm failed to load! |
try adding this to httpd.conf:
PerlModule Apache |
[ TOC ]
[ TOC ]
my() Scoped Variable in Nested Subroutines.
[ TOC ]
my() Scoped Variable in Nested Subroutines.
[ TOC ]
There is no object built for this module. e.g. when you see:
Can't locate loadable object for module Apache::Util in @INC... |
make sure to give mod_perl's Makefile.PL
PERL_UTIL_API=1
,
EVERYTHING=1
or DYNAMIC=1
parameters to enable and build all the components of Apache::Util
.
[ TOC ]
Can't locate object method "get_handlers" via package "Apache" |
You need to rebuild your mod_perl with stacked handlers, i.e.
PERL_STACKED_HANDLERS=1
or more simply EVERYTHING=1
.
[ TOC ]
Most often you will find that you really do have a syntax error. However
the other reason might be that a script running under
Apache::Registry
is using <__DATA__> or <__END__> tokens. See
Learn why
[ TOC ]
Check that all your modules are compiled with the same Perl that is compiled into mod_perl. Perl 5.005 and 5.004 are not binary compatible by default.
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 compatibility flags.
The solution to these problems is to rebuild Perl and any 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 |
Read Perl's INSTALL document for more details.
Solaris OS specific:
``Can't load DBI
'' or similar error for the IO module or whatever dynamic module 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 Configure
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.
[ TOC ]
[ TOC ]
Under mod_perl you may receive a warning or an error in the
error_log which specifies /dev/null as the source file, and line 0 as an line number where the printing of the
message was triggered. This is absolutely normal if the code is executed
from within a handler, because there is no actual file associated with the
handler. Therefore $0
is set to /dev/null and that's what you see.
[ TOC ]
See the sections ``Non-Scheduled Emergency Log Rotation'' and ``All RAM Consumed''
[ TOC ]
If you have some of the processes segfault when using XML::Parser
you should use
--disable-rule=EXPAT |
during the Apache configuration step.
Starting from mod_perl version 1.23 this option is disabled by default.
[ TOC ]
See My CGI/Perl Code Gets Returned as Plain Text Instead of Being Executed by the Webserver.
[ TOC ]
See Use of uninitialized value at (eval 80) line 12.
[ TOC ]
This message happens when the client breaks the connection while your
script is trying to write to the client. With Apache 1.3.x, you should only
see the rwrite messages if LogLevel
is set to debug
.
There was a bug that reported this debug message regardless of the value of
the LogLevel
directive. It was fixed in mod_perl 1.19_01 (CVS version).
Generally LogLevel
is either debug
or info
. debug
logs everything, info
is the next level, which doesn't include debug messages. You shouldn't use
``debug'' mode on your production server. At the moment there is no way to
prevent users from aborting connections.
[ TOC ]
Fixed in mod_perl 1.23.
[ TOC ]
[modperl] caught SIGPIPE in process 1234 [modperl] process 1234 going to Apache::exit with status... |
That's the $SIG{PIPE}
handler installed by mod_perl/Apache::SIG
, which is called if a connection times out or if the client presses the
'Stop' button. It gives you an opportunity to do cleanups if the script was
aborted in the middle of its execution. See Handling the 'User pressed Stop button' case
for more info.
If your mod_perl version is earlier than 1.17 you might also get the message in the following section...
[ TOC ]
Client hit STOP or Netscape bit it! Process 2493 going to Apache::exit with status=-2 |
You may see this message in mod_perl versions less than 1.17. See also caught SIGPIPE in process.
[ TOC ]
The script below will print a warning like that above, moreover it will print the whole script as a part of the warning message:
#!/usr/bin/perl -w use strict; print "Content-type: text/html\n\n"; print "Hello $undefined"; |
The warning:
Global symbol "$undefined" requires explicit package name at /usr/apps/foo/cgi/tmp.pl line 4. eval 'package Apache::ROOT::perl::tmp_2epl; use Apache qw(exit);sub handler { #line 1 /usr/apps/foo/cgi/tmp.pl BEGIN {$^W = 1;}#!/usr/bin/perl -w use strict; print "Content-type: text/html\\n\\n"; print "Hello $undefined"; } ;' called at /usr/apps/lib/perl5/site_perl/5.005/aix/Apache/Registry.pm line 168 Apache::Registry::compile('package Apache::ROOT::perl::tmp_2epl;use Apache qw(exit);sub han...') called at /usr/apps/lib/perl5/site_perl/5.005/aix/Apache/Registry.pm line 121 Apache::Registry::handler('Apache=SCALAR(0x205026c0)') called at /usr/apps/foo/cgi/tmp.pl line 4 eval {...} called at /usr/apps/foo/cgi/tmp.pl line 4 [Sun Nov 15 15:15:30 1998] [error] Undefined subroutine &Apache::ROOT::perl::tmp_2epl::handler called at /usr/apps/lib/perl5/site_perl/5.005/aix/Apache/Registry.pm line 135. [Sun Nov 15 15:15:30 1998] [error] Goto undefined subroutine &Apache::Constants::SERVER_ERROR at /usr/apps/lib/perl5/site_perl/5.005/aix/Apache/Constants.pm line 23. |
The error is simple to fix. When you use the use strict;
pragma (and you should...), Perl will insist that all variables are defined
before being used, so the error will not arise.
The bad thing is that sometimes the whole script (possibly, thousands of
lines) is printed to the error_log file as code that the server has tried to eval()
uate.
May be you have a $SIG{__DIE__}
handler installed (Carp::confess()
?). If so that's what's expected.
You might wish to try something more terse such as "local $SIG{__WARN__} = \&Carp::cluck;" The confess method is very verbose and will tell you more than you might wish to know including full source.
[ TOC ]
Your code includes some undefined variable that you have used as if it was already defined and initialized. For example:
$param = $q->param('test'); print $param; |
vs.
$param = $q->param('test') || ''; print $param; |
In the second case, $param
will always be defined
, either with
$q->param('test')
's return value, or if the parameter doesn't exist or is undef
ined then the empty string, ''
, will be assigned to $param
.
Also read about Finding the Line Which Triggered the Error or Warning.
[ TOC ]
See Names collisions with Modules and libs.
[ TOC ]
Callback called exit is just a generic message when some unrecoverable error occurs inside Perl
during perl_call_sv()
(which mod_perl uses to invoke all handler subroutines. Such problems seem
to occur far less with 5.005_03 than 5.004.
Sometimes you discover that your server is not responding and its error_log has filled up the remaining space on the file system. When you get to see the contents of the error_log -- it includes millions of lines, like:
Callback called exit at -e line 33, <HTML> chunk 1. |
Why the looping?
Perl can get very confused inside an endless loop in your code. It doesn't necessarily mean
that your code did call exit()
. Perl's malloc went haywire and called croak()
, but no memory is left to properly report the error, so Perl is stuck in a
loop writing that same message to stderr.
Perl 5.005+ plus is recommended for its improved malloc.c and other features that improve mod_perl and are turned on by default.
See also Out_of_memory!
[ TOC ]
If something goes really wrong with your code, Perl may die with an ``Out of memory!'' message and/or ``Callback called exit''. Common causes 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:
=item -DPERL_EMERGENCY_SBRK |
If PERL_EMERGENCY_SBRK is defined, running out of memory need not be a fatal error: a memory pool can allocated 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__}
handler will call Carp::confess
, giving you a stack trace which should reveal where the problem is. See
the Apache::Resource
module for prevention of spinning httpds.
Note that Perl 5.005 and later have PERL_EMERGENCY_SBRK
turned on by default.
The other trick is to have a startup script initialize
Carp::confess
, like so:
use Carp (); eval { Carp::confess("init") }; |
this way, when the real problem happens, Carp::confess
doesn't eat memory in the emergency pool ($^M
).
[ TOC ]
See Choosing MaxClients.
[ TOC ]
syntax error at /dev/null line 1, near "line arguments:" Execution of /dev/null aborted due to compilation errors. parse: Undefined error: 0 |
There is a chance that your /dev/null
device is broken. Try:
% sudo echo > /dev/null |
[ TOC ]
Can't call method "register_cleanup" on an undefined value at /usr/lib/perl5/5.00503/CGI.pm line 263. |
caused by this code snippet in CGI.pm:
if ($MOD_PERL) { Apache->request->register_cleanup(\&CGI::_reset_globals); undef $NPH; } |
One solution is to add to httpd.conf:
PerlPostReadRequestHandler 'sub { Apache->request(shift) }' |
But even better, switch to Apache::Cookie
:
use Apache; use Apache::Cookie; sub handler { my $r = shift; my $cookies = Apache::Cookie->new($r)->parse; my %bar = $cookies->{foo}->value; } |
[ TOC ]
[ TOC ]
Unfortunately, not all perl modules are robust enough to survive reload.
For them this is an unusual situation. PerlFreshRestart
does not much more than:
while (my($k,$v) = each %INC) { delete $INC{$k}; require $k; } |
Besides that, it flushes the Apache::Registry
cache, and empties any dynamic stacked handlers (e.g. PerlChildInitHandler
).
Lots of SegFaults and other problems were reported by users who had turned PerlFreshRestart
On. Most of them have gone away when it was turned off. It doesn't mean that
you shouldn't use it, if it works for you. Just beware of the dragons...
Note that if you have mod_perl enabled Apache built as DSO and you restart
it, the whole Perl interpreter is completely torn down (perl_destruct())and
restarted. The value of PerlFreshRestart
is irrelevent at this point.
[ TOC ]
That's a mandatory warning inside Perl which happens only if you modify
your script and Apache::Registry reloads it. Perl is warning you that the
subroutine(s)
were redefined. It is mostly harmless. If you
don't like seeing these warnings, just kill -USR1
(graceful restart) Apache when you modify your scripts.
You aren't supposed to see these warnings if you don't modify the code with
perl 5.004_05 or 5.005+.and higher. If you still experience a problem with
code within a CGI script, moving all the code into a module (or a library)
and require()ing
it should solve the problem.
[ TOC ]
Can't undef active subroutine at /usr/apps/lib/perl5/site_perl/5.005/aix/Apache/Registry.pm line 102. Called from package Apache::Registry, filename /usr/apps/lib/perl5/site_perl/5.005/aix/Apache/Registry.pm, line 102 |
This problem is caused when a client drops the connection while httpd is in the middle of a write. httpd times out, sending a SIGPIPE, and Perl (in that child) is stuck in the middle of its eval context. This is fixed by the Apache::SIG module which is called by default. This should not happen unless you have code that is messing with $SIG{PIPE}. It's also triggered only when you've changed your script on disk and mod_perl is trying to reload it.
[ TOC ]
From mod_perl.pod: With Apache versions 1.3.0 and higher, mod_perl will
call the perl_destruct()
Perl API function during the child
exit phase. This will cause proper execution of END
blocks found during server startup as well as invoking the DESTROY
method on global objects which are still alive. It is possible that this
operation may take a long time to finish, causing problems during a
restart. If your code does not contain any END
blocks or DESTROY
methods which need to be run during child server shutdown, this destruction
can be avoided by setting the PERL_DESTRUCT_LEVEL
environment variable to -1
. Be aware that `your code' includes any modules you use and they may well have DESTROY
and END
blocks...
[ TOC ]
If you see a process stuck in ``G'' (Gracefully finishing) after a doing a
graceful restart (sending kill -SIGUSR1) it means that the process is hanging in perl_destruct()
while trying to cleanup. This cleanup normally isn't a requirement, you can
disable it by setting the PERL_DESTRUCT_LEVEL environment variable to -1.
See the section ``Speeding up the Apache Termination and Restart'' for more information.
[ TOC ]
[ TOC ]
Apache::DBI
causes the server to exit when it starts up, with:
[Mon Oct 25 15:06:11 1999] file .\main\http_main.c, line 5890, assertion "start_mutex" failed |
Solution: build mod_perl with PERL_STARTUP_DONE_CHECK
set (e.g. insert
#define PERL_STARTUP_DONE_CHECK 1 |
at the top of mod_perl.h or add it to the defines in the MSVC++ and similar applications' Options
dialog).
Apache loads all Apache modules twice, to make sure the server will
successfully restart when asked to. This flag disables all
PerlRequire
and PerlModule
statements on the first load, so they can succeed on the second load.
Without that flag, the second load fails.
[ TOC ]
Your corrections of the technical and grammatical
errors are very welcome. You are encouraged to help me
improve this guide. If you have something to contribute
please send it
directly to me.
|
The
Writing Apache Modules with Perl and C
book can be purchased online from O'Reilly
and
Amazon.com.
|
Written by Stas Bekman. Last Modified at 10/20/2000 |
|
Use of the Camel for Perl is a trademark of O'Reilly & Associates, and is used by permission. |