The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

Porting Apache:: Modules from mod_perl 1.0 to 2.0

Description

If you have released an Apache::Foo module on CPAN you may wonder what steps you should take to make your code working under mod_perl 2.0 while still preserving 1.0 compatibility. This document attempts to answer some of the questions related to this issue.

Should the Module Name Be Changed?

While you can change the name of the module, it's the best to try to preserve the name and use some workarounds if your module cannot be ported to run under 1.0 and 2.0 at the same time.

Most of the CPAN Apache:: modules for mod_perl 1.0 should work with mod_perl 2.0 without any change. Modules including XS code may or may not work, depending on whether they use Apache API that have changed in Apache 2.0.

Let's say that you have a module Apache::Friendly whose release version complient with mod_perl 1.0 is 1.57. You keep this version on CPAN and release a new version 2.01 which is complient with 2.0 and preserves the name of the module. It's possible that a user may need to have both versions of the module on the same machine. Since the two have the same name they obviously cannot live under the same tree. One attempt to solve that problem is to use MP_INST_APACHE2 Makefile.PL's option. If the module is configured as:

  % perl Makefile.PL MP_INST_APACHE2=1

it'll be installed relative to the Apache2/ directory.

META: but of course this won't work in non-core mod_perl, since a generic Makefile.PL has no idea what to do about MP_INST_APACHE2=1. Need to provide copy-n-paste recipe for this. Or even add to the core a supporting module that will handle this functionality.

The second step is to change the documentation of your 2.0 complient module to say:

  use Apache2 ();

in the code before the module is required or in startup.pl or

  PerlModule Apache2

in httpd.conf. This will @INC to look in the Apache2/ directory first.

The introduction of Apache2/ directory is similar to how Perl installs its modules in a version specific directory. For example:

  lib/5.7.1
  lib/5.7.2

Requiring a specific mod_perl version.

To require a module to run only under 2.0, simply add:

  use mod_perl 2.0;

to your module. You can also use the variable $mod_perl::VERSION.

In the configuration file you can use a special configuration define MODPERL2 which is enabled internally, as if the server had been started with -DMODPERL2.

 <IfDefine MODPERL2>
     # 2.0 configuration
 </IfDefine>
 <IfDefine !MODPERL2>
     # else
 </IfDefine>

From within Perl code this can be tested with Apache::exists_config_define(), for example:

  if (Apache::exists_config_define("MODPERL2")) {
      # some 2.0 specific code
  }

Adjusting Modules to Work with 1.0 and 2.0.

It's possible to adjust your module to work with both 2.0 and 1.0. This is quite easy if your aren't using XS. Interfaces that are deprecated in 2.0 can be enabled by adding:

  use Apache::compat();

in the code or startup.pl.

The variable $mod_perl::VERSION should be used in conditionals to use the appropriate code for 1.0 or 2.0. You can use it to load Apache::compat if running under mod_perl 2.0:

  if ($mod_perl::VERSION >= 2.0) {
      require Apache::compat;
  }

XS modules will need Makefile.PL/#ifdef logic to work with both versions. But the applications that use them should not need to know the difference.

META: example? probably the best to use some existing module that co-exists with the two versions.

Thread Safety

META: to be written

  #ifdef MP_THREADED
      /* threads specific code goes here */
  #endif

PerlIO

PerlIO layer has become usable only in perl 5.8.0, so if you plan on working with PerlIO, you can use the PERLIO_LAYERS constant. e.g.:

  #ifdef PERLIO_LAYERS
  #include "perliol.h"
  #else 
  #include "iperlsys.h"
  #endif

'make test' Suite

Apache::Test testing framework that comes together with mod_perl 2.0 works with 1.0 and 2.0 mod_perl versions. Therefore you should consider porting your test suite to use the Apache::Test Framework.

Apache C Code Specific Notes

Apache Core Documentation

Most of documentation dedicated for migration to Apache 2.0 can be found at: http://httpd.apache.org/docs-2.0/developer/

The Apache 2.0 API documentation now resides in the C header files, which can be conveniently browsed via http://docx.webperf.org/.

The APR API documentation can be found here http://apr.apache.org/.

The new Apache and APR APIs include many new functions. Though certain functions have been preserved, either as is or with a changed prototype (for example to work with pools), others have been renamed. So if you are porting your code and the function that you've used doesn't seem to exist in Apache 2.0, first refer to the "compat" header files, such as: include/ap_compat.h, srclib/apr/include/apr_compat.h, and srclib/apr-util/include/apu_compat.h, which list functions whose names have changed but which are otherwise the same. If failed, proceed to look in other headers files in the following directories:

  • ap_ functions in include/

  • apr_ functions in srclib/apr/include/ and srclib/apr-util/include/

ap_soft_timeout(), ap_reset_timeout(), ap_hard_timeout() and ap_kill_timeout()

If the C part of the module in 1.0 includes ap_soft_timeout(), ap_reset_timeout(), ap_hard_timeout() and ap_kill_timeout() functions simply remove these in 2.0. There is no replacement for these functions because Apache 2.0 uses non-blocking I/O. As a side-effect of this change, Apache 2.0 no longer uses SIGALRM, which has caused conflicts in mod_perl 1.0.

Maintainers

Maintainer is the person(s) you should contact with updates, corrections and patches.

Stas Bekman <stas (at) stason.org>

Authors

  • Stas Bekman <stas (at) stason.org>

  • Doug MacEachern <dougm (at) covalent.net>

Only the major authors are listed above. For contributors see the Changes file.