Practical mod_perl, from O'Reilly. | 18 | WebReference

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:

use subs qw(exit);
exit(  ) if $DEBUG;
sub exit { warn "exit(  ) was called"; }

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:


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:

my $r = shift;
sub exit_child {
    # some logic here if needed

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.

Created: March 27, 2003
Revised: July 23, 2003