Apache::ChildExit - Modify ModPerl Apache::Registry's treatment of END blocks


Each script executed by Apache::Registry should contain the following statements:

  use Apache::ChildExit ;
  Apache::ChildExit::Postpone() ;


  use Apache::ChildExit qw( Postpone ) ;
  Postpone() ;

The Postpone() function should be called in the last line of your script.


## Example

  use Apache::ChildExit qw( Postpone ) ;

  ## ...user code...
  printf "%d\n", Apache::ChildExit::ENDBlockCount() ;   # 4
  printf "%d\n", Apache::ChildExit::PostponedCount() ;  # 0

  Postpone() ;
  printf "%d\n", Apache::ChildExit::ENDBlockCount() ;   # 0
  printf "%d\n", Apache::ChildExit::PostponedCount() ;  # 4

  ## ...user code...
  printf "%d\n", Apache::ChildExit::ENDBlockCount() ;   # 3
  printf "%d\n", Apache::ChildExit::PostponedCount() ;  # 4

  Postpone() ;
  printf "%d\n", Apache::ChildExit::ENDBlockCount() ;   # 0
  printf "%d\n", Apache::ChildExit::PostponedCount() ;  # 7

  ## Child process terminates
  Apache::ChildExit::ChildExit() ;

As part of Apache::Registry's design, the BEGIN blocks' code executes only once when a module is compiled. But the END blocks are executed every time the enclosing script runs. Consequently, Apache::Registry is incompatible with the standard Perl specification, which balances the execution of the BEGIN and END blocks. Modules that use these blocks to allocate and deallocate resources will behave quite badly when run under Apache::Registry, possibly damaging other system resources.

In Perl, each END block is represented by a code reference. Apache::ChildExit moves these references into a private array. Subsequently, the code blocks are not executed until the ChildExit phase of Apache's operation.

In the above example, 4 END blocks are encountered while compiling the first block of user code. 3 additional END blocks are encountered while compiling the second block of user code. After each block of user code, the Postpone() command moves the END block code references.

Apache::Registry compiles each script upon request by the web server. After running the script, Apache::Registry will execute each of the encountered END blocks. In order to prevent execution of the END blocks, the Postpone() function should be the last line of code in each script.

The Postpone() function should not be successfully called without an eventual call to the ChildExit() function, or indirectly, the handler() function. As a safeguard, the Postpone() function ensures the Apache::Registry environment by checking the caller package. If the caller package is main, the Postpone() function call has no effect. Postpone() will complain Unrecognized caller package if called outside of the above guidelines.

In order to comply with the Perl specification, the END blocks are executed by the handler function during the ChildExit phase of an Apache process. The following line needs to be added to httpd.conf:

        PerlChildExitHandler Apache::ChildExit


None by default.


Jim Schueler, <>