Different modules, same names, random results
Hello everyone, I am currently running a web server using Perl CGI for all my web sites and have been attracted to mod_perl for the performance advantages - particularly not having to start a new perl interpreter for each request. I have tried using Apache::Register and Apache::PerlRun but am having problems due to the fact that each web site refers to their own copy of my module called Site.pm (to contain functions, global variables etc). The problem is that the my scripts get confused and use variables from the other site's modules randomly. The following example is using Apache::PerlRun (as it's supposed to be more forgiving that Apache::Register). I am using Apache 1.3.26 and mod_perl 1.26 on Debian Woody. .htaccess - PerlModule Apache::PerlRun files *.pl SetHandler perl-script PerlHandler Apache::PerlRun Options +ExecCGI /files site1.pl #!/usr/bin/perl use strict; use CGI; use lib lib1; use Site; my $q = new CGI; print $q-header(); print EOF; Site 1br VAR: $VARbr EOF lib1/Site.pm #!/usr/bin/perl -w package Site; require Exporter; use strict; our $VAR = Site one; our @ISA = qw(Exporter); our @EXPORT = qw($VAR); 1; site2.pl #!/usr/bin/perl use strict; use CGI; use lib lib2; use Site; my $q = new CGI; print $q-header(); print EOF; Site 2br VAR: $VARbr EOF lib2/Site.pm #!/usr/bin/perl -w package Site; require Exporter; use strict; our $VAR = Site two; our @ISA = qw(Exporter); our @EXPORT = qw($VAR); 1; I then call site1.pl and site2.pl multiple times and get output like this: Site 1 VAR: Site two Site 1 VAR: Site one Site 1 VAR: Site two Site 2 VAR: Site two Site 2 VAR: Site two Site 2 VAR: Site one I can fix this problem by adding the line PerlSetVar PerlRunOnce On to my .htaccess file, but my performance tests show that this is actually slower than regular CGI!! Is there anything I can do to make this work properly without renaming all my Site.pm modules (and all scripts that call them) to have unique names? Thanks, Pinunki __ Do you Yahoo!? Yahoo! Mail Plus - Powerful. Affordable. Sign up now. http://mailplus.yahoo.com
Re: Different modules, same names, random results
this is probably evil, and apologies to those who have seen suspiciously familiar code before, but is this possible? package MyPrefix::Apache::Registry; use strict; BEGIN { use Apache::Registry(); } sub handler { delete $INC{'Site.pm'}; # mess with @INC require Site; return (Apache::Registry::handler(@_)); } END { } 1; that would allow you to keep perl resident, keep the cgi-scrip resident and simply reload a small? configuation perl module each time. (i think?) :) Uru -Dave Pinunki wrote: Hello everyone, I am currently running a web server using Perl CGI for all my web sites and have been attracted to mod_perl for the performance advantages - particularly not having to start a new perl interpreter for each request. I have tried using Apache::Register and Apache::PerlRun but am having problems due to the fact that each web site refers to their own copy of my module called Site.pm (to contain functions, global variables etc). The problem is that the my scripts get confused and use variables from the other site's modules randomly. The following example is using Apache::PerlRun (as it's supposed to be more forgiving that Apache::Register). I am using Apache 1.3.26 and mod_perl 1.26 on Debian Woody. .htaccess - PerlModule Apache::PerlRun files *.pl SetHandler perl-script PerlHandler Apache::PerlRun Options +ExecCGI /files site1.pl #!/usr/bin/perl use strict; use CGI; use lib lib1; use Site; my $q = new CGI; print $q-header(); print EOF; Site 1br VAR: $VARbr EOF lib1/Site.pm #!/usr/bin/perl -w package Site; require Exporter; use strict; our $VAR = Site one; our @ISA = qw(Exporter); our @EXPORT = qw($VAR); 1; site2.pl #!/usr/bin/perl use strict; use CGI; use lib lib2; use Site; my $q = new CGI; print $q-header(); print EOF; Site 2br VAR: $VARbr EOF lib2/Site.pm #!/usr/bin/perl -w package Site; require Exporter; use strict; our $VAR = Site two; our @ISA = qw(Exporter); our @EXPORT = qw($VAR); 1; I then call site1.pl and site2.pl multiple times and get output like this: Site 1 VAR: Site two Site 1 VAR: Site one Site 1 VAR: Site two Site 2 VAR: Site two Site 2 VAR: Site two Site 2 VAR: Site one I can fix this problem by adding the line PerlSetVar PerlRunOnce On to my .htaccess file, but my performance tests show that this is actually slower than regular CGI!! Is there anything I can do to make this work properly without renaming all my Site.pm modules (and all scripts that call them) to have unique names? Thanks, Pinunki __ Do you Yahoo!? Yahoo! Mail Plus - Powerful. Affordable. Sign up now. http://mailplus.yahoo.com
Re: Different modules, same names, random results
David Dick wrote: this is probably evil, and apologies to those who have seen suspiciously familiar code before, but is this possible? package MyPrefix::Apache::Registry; use strict; BEGIN { use Apache::Registry(); } sub handler { delete $INC{'Site.pm'}; # mess with @INC require Site; return (Apache::Registry::handler(@_)); } a simpler way is to do: do Site.pm; though you forgot to call the import, when removing use, so you do: do Site.pm; Site-import(whatever); and if you use: use warnings; you probably want to add: no warnings 'redefine'; END { } 1; that would allow you to keep perl resident, keep the cgi-scrip resident and simply reload a small? configuation perl module each time. (i think?) :) indeed. This is discussed here: http://perl.apache.org/docs/1.0/guide/porting.html#Name_collisions_with_Modules_and_libs __ Stas BekmanJAm_pH -- Just Another mod_perl Hacker http://stason.org/ mod_perl Guide --- http://perl.apache.org mailto:[EMAIL PROTECTED] http://use.perl.org http://apacheweek.com http://modperlbook.org http://apache.org http://ticketmaster.com
Re: Different modules, same names, random results
Pinunki wrote: [...] I have tried using Apache::Register and Apache::PerlRun but am having problems due to the fact that each web site refers to their own copy of my module called Site.pm (to contain functions, global variables etc). The problem is that the my scripts get confused and use variables from the other site's modules randomly. [...] If your module which has an indentical name but different contents and it never calls functions and accesses variables by prefixing the module name (e.g. Site::foo and $Site::bar), i.e. everything is exported, you could hack Apache::Registry to compile the different files into different package names and do the importing for you. Here is the proof of concept (untested!) code. All it does, is reading the file (Site.pm in your case), prepending the string 'package foo_bar_tar_lib1_Site_pm;' to the contents of the file, compiling the module via eval and then calling import() to import all the stuff as it did before. Notice that you do have to change your scripts to call the trickery my_use(). (Alternatively you could try to play with aliasing of the namespaces, instead of mangling the file contents, but this could introduce problems...) my_script.pl: - my @imports(); Apache::Registry::my_use('Site.pm', @imports); Site.pm --- # no package declaration! # the rest is as usual Exporter, vars, subs # blah, blah 1; Registry.pm --- package Apache::Registry; # the normal Registry stuff ... # then the extra stuff: use File::Spec::Functions; sub my_use { my($module, @import) = @_; my $file = catfile Apache-request-filename, $module; my $namespace = make_namespace($file); compile($namespace, $file) or die failed to compile: $@; $namespace-import(@import); } sub make_namespace { my ($path) = @_; $path =~ s/([^A-Za-z0-9_])/sprintf(_%2x, unpack(C, $1))/eg; # make sure that the sub-package doesn't start with a digit $path =~ s/^(\d)/_$1/; return $path; } sub compile { my ($namespace, $file) = @_; open my $fh, $file; local $/; my $data = $fh; close $fh; { eval package $namespace;\n $data; } return $@ ? 0 : 1; } 1; __ Stas BekmanJAm_pH -- Just Another mod_perl Hacker http://stason.org/ mod_perl Guide --- http://perl.apache.org mailto:[EMAIL PROTECTED] http://use.perl.org http://apacheweek.com http://modperlbook.org http://apache.org http://ticketmaster.com