Restart or termination of a mod_perl server may sometimes take quite a long time, perhaps even tens of seconds. The reason for this is a call to the perl_destruct( ) function during the child exit phase, which is also known as the cleanup phase. In this phase, the Perl END blocks are run and the DESTROY method is called on any global objects that are still around.

Sometimes this will produce a series of messages in the error_log file, warning that certain child processes did not exit as expected. This happens when a child process, after a few attempts have been made to terminate it, is still in the middle of perl_destruct( ). So when you shut down the server, you might see something like this:

[warn]   child process 7269 still did not exit,
         sending a SIGTERM
[error]  child process 7269 still did not exit,
         sending a SIGKILL
[notice] caught SIGTERM, shutting down

First, the parent process sends the TERM signal to all of its children, without logging a thing. If any of the processes still doesn't quit after a short period, it sends a second TERM, logs the PID of the process, and marks the event as a warning. Finally, if the process still hasn't terminated, it sends the KILL signal, which unconditionaly terminates the process, aborting any operation in progress in the child. This event is logged as an error.

If the mod_perl scripts do not contain any END blocks or DESTROY methods that need to be run during shutdown, or if the ones they have are nonessential, this step can be avoided by setting the PERL_DESTRUCT_LEVEL environment variable to -1. (The -1 value for PERL_DESTRUCT_LEVEL is special to mod_perl.) For example, add this setting to the httpd.conf file:

PerlSetEnv PERL_DESTRUCT_LEVEL -1

What constitutes a significant cleanup? Any change of state outside the current process that cannot be handled by the operating system itself. Committing database transactions and removing the lock on a resource are significant operations, but closing an ordinary file is not. For example, if DBI is used for persistent database connections, Perl's destructors should not be switched off.