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

Hi, I have an antique Perl script that was designed poorly and makes use of a ton of global variables to work properly. Data is simply assigned to a variable or hash, to be later called upon somewhere else in the script. For example, a username is determined with $uid = &check();. $uid is global and remains accessible until the script terminates. This really isn't a problem when using Apache and regular CGI, but I'd like to move the script to FastCGI for obvious reasons. It would require a major rewrite for various subroutines to return constantly rather than setting variables in a global scope. -- Its really not an option --. There must be some way to encapsulate the main functions of the program to automagically my (private) / localize anything used within the encapsulation. Really love to hear your thoughts on this one. _Kevin
  • Comment on Private Variables and FastCGI / ModPerl

Replies are listed 'Best First'.
Re: Private Variables and FastCGI / ModPerl
by Anonymous Monk on Feb 11, 2010 at 07:32 UTC
      So localizing seems to be thing to do here. There are just too many variables to be localized. I've found that using Devel::Symdump lets me dump all the symbols used in the program.
      $globalthis = 0; $globalthat = 0; require Devel::Symdump; $obj = Devel::Symdump->new(); @array = $obj->scalars; foreach (@array){ print "$_\n"; }
      How can I local everything in @array? I know its probably extremely dangerous, so I will most likely build a difference table between what is in @array without anything loaded and then again with. Any help is appreciated.
Re: Private Variables and FastCGI / ModPerl
by Anonymous Monk on Feb 11, 2010 at 03:23 UTC
    - Its really not an option --. There must be some way to encapsulate the main functions of the program to automagically my (private) / localize anything used within the encapsulation. Really love to hear your thoughts on this one. _Kevin

    They call that a rewrite, anything else is just prayer

      Using local $var seems to be the fix for such problems. Although it may/may not work with mod_perl, it seems to work fine within the FCGI loop.
      use FCGI; while (FCGI::accept >= 0) { local $cnt; local $last_elapsed; ############### &http(0); &head(); &t(''); print "OK"; &t(''); &t(''); my $cc; while ($cc < 1000){ &test; $cc++; } } sub test(){ print "CNT: $cnt"; $cnt++; }
      Thank you for your prompt response. Alright perhaps you can help me with this then... How can I keep variables results within a subroutine as if they were global? The following sub is used to see how long portions of code take to execute. But how can I keep $last_elapsed within the sub?
      use Time::HiRes qw(tv_interval); &t('Reference Time'); sleep(2); &t('Did something'); sub t(){ my $t0 = [gettimeofday]; my $elapsed = tv_interval ( $t0 ); my $elapsed_o = $elapsed; $elapsed = $elapsed - $last_elapsed; if ($last_elapsed){printf ("(%s)%f<br>\n",$_[0],$elapsed);} $last_elapsed = $elapsed_o; }
      Hope to hear from you, _Kevin
        #!/usr/bin/perl -- use strict; use warnings; use Time::Elapse; Main(@ARGV); exit(0); sub Main { Time::Elapse->lapse( my $now = 'Reference Time' ); print "$now\n"; sleep 2; print "$now\n"; sleep 1; $now = 'Did something'; print "$now\n"; } ## end sub Main __END__ 16:00:00.000064 [Reference Time] 16:00:02.000000 [Reference Time] 16:00:00.000069 [Did something]