sliver has asked for the wisdom of the Perl Monks concerning the following question:

Thanks in advance to anyone who can help me...

I am writing a fairly large site that breaks up common functions into multiple libraries that are loaded by calling a single module (LOADER.pm).

This is the code for LOADER.pm:
package LOADER; require Exporter; use vars qw( $ROOTDIR $ROOTSERVER $ROOTNAME @importList @onDemandImportList %onDemandGroups @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS $VERSION ); $ROOTDIR = '/some/dir/'; $ROOTSERVER = 'someurl.com'; $ROOTNAME = 'some name'; @importList = qw( $ROOTDIR $ROOTNAME $ROOTSERVER ); @onDemandImportList; %onDemandGroups; require qq|$ROOTDIR/LIBS/FUNCTIONS.pl|; require qq|$ROOTDIR/LIBS/HTML.pl|; require qq|$ROOTDIR/LIBS/TEMPLATE.pl|; require qq|$ROOTDIR/LIBS/FORM.pl|; require qq|$ROOTDIR/LIBS/IMAGE.pl|; require qq|$ROOTDIR/LIBS/USER.pl|; require qq|$ROOTDIR/LIBS/SECURE.pl|; require qq|$ROOTDIR/LIBS/BOARD.pl|; require qq|$ROOTDIR/LIBS/GLOBALS.pl|; require qq|$ROOTDIR/LIBS/INIT.pl|; @ISA = qw(Exporter); @EXPORT = @importList; @EXPORT_OK = @onDemandImportList; %EXPORT_TAGS = %onDemandGroups; $VERSION = 1.00;

For example, say have libs: A.pl, B.pl, and C.pl. The LOADER.pm package would only load those functions from those libs as called by the referring script (ie use LOADER qw(some functions); by using a require for each lib)

Problem is... I have two libs that contain globals, one that contains static globals (GLOBALS.pl) and one that contains dynamic globals (INIT.pl) that are dependent on the request from the user. Some of these globals are the args variable and some security and account globals.

This works fine running normally under Perl and Apache, but I would like to use mod_perl. The site works fine for the first few loads, but as soon as the child processes are called again the dynamic globals get all mixed up. I've been told Globals should always be avoided, but I could not think of other ways of sharing info across all libs and the calling script.

I declare all globals with use vars and I tried using a "do" rather than "require" for the dynamic lib in the package call... still no luck. I just want the globals to be refreshed (basically rerun the dynamic lib) every time a script is run.

Any ideas?

Replies are listed 'Best First'.
Re: mod perl global initialization
by sgifford (Prior) on May 11, 2004 at 03:55 UTC
    If you want all of the variables from INIT.pl set back to undef for every request, you can simply write a function that resets them all, put it in INIT.pl, then call it at the top of your mod_perl script.
Re: mod perl global initialization
by Tomte (Priest) on May 11, 2004 at 09:00 UTC

    As the static globals aren't a concern, I'll concentrate on a proposal for your INIT.pl

    I wouldn't use INIT.pl as global-variables repository. Instead I would define and export a sub in it, that'd assamble the dynamic init-stuff into a hash and return this. Instead of using

    INIT::thisvar; INIT::thatvar
    you had to use
    INIT::getInitvars()->{thisvar}; INIT::getInitvars()->{thatvar};
    or, better yet
    my $initHash = INIT::getInitvars() $initHash->{thisvar}; $initHash->{thatvar};
    the Module could look like this (not working code, just a pseudo-perl example out of nothing):
    package INIT; use Exporter; use vars qw( %static_1 %static_2 ); @ISA = qw(Exporter); @EXPORT = qw(&getInitvars); @EXPORT_OK = qw(%static_1 %static_2); %static_1 = ( this => "that", ); %static_2 = ( that => "this", ); sub getInitvars { my $result = {}; # push the static stuff push @$result, %static_1; push @$result, %static_2; # create the dynamic stuff push @result, _dynamicStuff(); $result; } sub _dynamicStuff { # compute stuff and return a hash }
    Using non-static, not-constant global variables is likely to create a maintenance nightmare; avoid them where possible; using a solution as the proposed isn't much more work, but easily expanded if your needs change.

    Edit: declared the static hashes, looks betterthat way;-)

    regards,
    tomte


    An intellectual is someone whose mind watches itself.
    -- Albert Camus

Re: mod perl global initialization
by BUU (Prior) on May 11, 2004 at 04:11 UTC
    hahah. You could use reset.
Re: mod perl global initialization
by perrin (Chancellor) on May 11, 2004 at 17:11 UTC
    You really shouldn't be using globals for this kind of non-persistent data, and you should be using perl5-style modules with package declarations in them instead of this perl4-ish .pl stuff. However, there is information in the mod_perl docs about how to use globals safely. I would suggest that ultimately you will want to use lexical (my) variables for the per-request stuff, or possible make an object to hold them.
Re: mod perl global initialization
by sliver (Initiate) on May 11, 2004 at 16:39 UTC
    Thanks everyone... you guys gave me a great and easy idea for a fix. I sort of combined your suggestions... i just wrapped my entire INIT.pl in a sub called initGlobals() and undef all the Globals first then populate them with the info. Then, all I had to do was just add initGlobals(); to all of my mod perl scripts. So far it's working... :)

    THANKS EVERYONE!!!