Practical mod_perl, from O'Reilly. | 18

Practical mod_perl: Chapter 6:
Coding with mod_perl in Mind

Perl Specifics in the mod_perl Environment

In the following sections, we discuss the specifics of Perl's
behavior under mod_perl.

exit( )

Perl's core exit( ) function shouldn't
be used in mod_perl code. Calling it causes the mod_perl process to exit, which
defeats the purpose of using mod_perl. The Apache::exit(
) function should be used instead. Starting with Perl Version 5.6.0,
mod_perl overrides exit( ) behind the scenes using
CORE::GLOBAL::, a new magical
package.

The CORE:: Package

CORE:: is a special
package that provides access to Perl's built-in functions. You may need
to use this package to override some of the built-in functions. For
example, if you want to override the exit( )
built-in function, you can do so with:

Now
when you call exit( ) in the same scope
in which it was overridden, the program won't exit, but instead will
just print a warning "exit( ) was called". If you want to
use the original built-in function, you can still do so with:

# the 'real' exit

CORE::exit( );

Apache::Registry and Apache::PerlRun
override exit( ) with Apache::exit(
) behind the scenes; therefore, scripts running under these modules don't
need to be modified to use Apache::exit( ).

If CORE::exit( ) is used in scripts
running under mod_perl, the child will exit, but the current request won't be
logged. More importantly, a proper exit won't be performed. For example, if
there are some database handles, they will remain open, causing costly memory
and (even worse) database connection leaks.

If the child process needs to be killed, Apache::exit(Apache::Constants::DONE)
should be used instead. This will cause the server to exit gracefully, completing
the logging functions and protocol requirements.

If the child process needs to be killed cleanly after the request
has completed, use the $r->child_terminate method.
This method can be called anywhere in the code, not just at the end. This method
sets the value of the MaxRequestsPerChild configuration
directive to 1 and clears the keepalive
flag. After the request is serviced, the current connection is broken because
of the keepalive flag, which is set to false, and
the parent tells the child to cleanly quit because MaxRequestsPerChild
is smaller than or equal to the number of requests served.

In an Apache::Registry script you
would write:

Apache->request->child_terminate;

and in httpd.conf:

PerlFixupHandler "sub { shift->child_terminate }"

You would want to use the latter example only if you wanted the
child to terminate every time the registered handler was called. This is probably
not what you want.

You can also use a post-processing handler to trigger child termination.
You might do this if you wanted to execute your own cleanup code before the
process exits:

This is the code that is used by the Apache::SizeLimit
module, which terminates processes that grow bigger than a preset quota.

die( )

die( ) is usually used to abort the
flow of the program if something goes wrong. For example, this common idiom
is used when opening files:

open FILE, "foo" or die "Cannot open 'foo' for reading: $!";

If the file cannot be opened, the script will die(
): script execution is aborted, the reason for death is printed, and
the Perl interpreter is terminated.

You will hardly find any properly written Perl scripts that don't
have at least one die( ) statement in them.

CGI scripts running under mod_cgi exit on completion, and the
Perl interpreter exits as well. Therefore, it doesn't matter whether the interpreter
exits because the script died by natural death (when the last statement in the
code flow was executed) or was aborted by a die( )
statement.

Under mod_perl, we don't want the process to quit. Therefore,
mod_perl takes care of it behind the scenes, and die(
) calls don't abort the process. When die( )
is called, mod_perl logs the error message and calls Apache::exit(
) instead of CORE::die( ). Thus, the script
stops, but the process doesn't quit. Of course, we are talking about the cases
where the code calling die( ) is not wrapped inside
an exception handler (e.g., an eval { } block)
that traps die( ) calls, or the $SIG{_
_DIE_ _} sighandler, which allows you to override the behavior of die(
) (see Chapter 21). The reference section at the end of this chapter
mentions a few exception-handling modules available from CPAN.