Practical mod_perl, from O'Reilly. | 16

Practical mod_perl: Chapter 6: Coding with mod_perl in Mind

Name Collisions with Modules and Libraries

In this section, we'll look at two scenarios with failures related to namespaces. For the following discussion, we will always look at a single child process.

A first faulty scenario

It is impossible to use two modules with identical names on the same server. Only the first one found in a use( ) or a require( ) statement will be loaded and compiled. All subsequent requests to load a module with the same name will be skipped, because Perl will find that there is already an entry for the requested module in the %INC hash.

Let's examine a scenario in which two independent projects in separate directories, projectA and projectB, both need to run on the same server. Both projects use a module with the name MyConfig.pm, but each project has completely different code in its MyConfig.pm module. This is how the projects reside on the filesystem (all located under the directory /home/httpd/perl):

projectA/MyConfig.pm
projectA/run.pl
projectB/MyConfig.pm
projectB/run.pl

Examples 6-6, 6-7, 6-8, and 6-9 show some sample code.

Example 6-6: projectA/run.pl

use lib qw(.);
use MyConfig;
print "Content-type: text/plain\n\n";
print "Inside project: ", project_name(  );

Example 6-7: projectA/MyConfig.pm

sub project_name { return 'A'; }
1;

Example 6-8: projectB/run.pl

use lib qw(.);
use MyConfig;
print "Content-type: text/plain\n\n";
print "Inside project: ", project_name(  );

Example 6-9: projectB/MyConfig.pm

sub project_name { return 'B'; }
1;

Both projects contain a script, run.pl, which loads the module MyConfig.pm and prints an indentification message based on the project_name( ) function in the MyConfig.pm module. When a request to /perl/projectA/run.pl is issued, it is supposed to print:

Inside project: A

Similarly, /perl/projectB/run.pl is expected to respond with:

Inside project: B

When tested using single-server mode, only the first one to run will load the MyConfig.pm module, although both run.pl scripts call use MyConfig. When the second script is run, Perl will skip the use MyConfig; statement, because MyConfig.pm is already located in %INC. Perl reports this problem in the error_log:

Undefined subroutine
&Apache::ROOT::perl::projectB::run_2epl::project_name called at
/home/httpd/perl/projectB/run.pl line 4.

This is because the modules didn't declare a package name, so the project_name( ) subroutine was inserted into projectA/run.pl's namespace, Apache::ROOT::perl::projectB::run_2epl. Project B doesn't get to load the module, so it doesn't get the subroutine either!

Note that if a library were used instead of a module (for example, config.pl instead of MyConfig.pm), the behavior would be the same. For both libraries and modules, a file is loaded and its filename is inserted into %INC.

A second faulty scenario

Now consider the following scenario:

project/MyConfig.pm
project/runA.pl
project/runB.pl

Now there is a single project with two scripts, runA.pl and runB.pl, both trying to load the same module, MyConfig.pm, as shown in Examples 6-10, 6-11, and 6-12.

Example 6-10: project/MyConfig.pm

sub project_name { return 'Super Project'; }
1;

Example 6-11: project/runA.pl

use lib qw(.);
use MyConfig;
print "Content-type: text/plain\n\n";
print "Script A\n";
print "Inside project: ", project_name(  );

Example 6-12: project/runB.pl

use lib qw(.);
use MyConfig;
print "Content-type: text/plain\n\n";
print "Script B\n";
print "Inside project: ", project_name(  );

This scenario suffers from the same problem as the previous two-project scenario: only the first script to run will work correctly, and the second will fail. The problem occurs because there is no package declaration here.

We'll now explore some of the ways we can solve these problems.

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

URL: http://webreference.com/programming/perl/mod_perl/chap6/1