in reply to Re^2: My, subroutines, scope, and CGI – Why can I see a private (my) variable in a subroutine but it doesn’t get updated?
in thread My, subroutines, scope, and CGI – Why can I see a private (my) variable in a subroutine but it doesn’t get updated?

Re mod_perl keeping old values in scope:
Can I stop it? Should I? Should I just reinitialize the variable in the subroutine the same way I do in the main script? Why does it do that?
Mod_perl (or more precisely, Apache::Registry) converts scripts to subroutines so they can be re-used without recompiling. Basically, if you have a script like this:
my $var = param('something'); sub print_var { print $var; } print_var();
It will get converted to something like this:
sub run_my_script { my $var = param('something'); sub print_var { print $var; } print_var(); }
And you should get a Variable "$var" will not stay shared warning in your error log.

AFAIK what happens is that in perl you can't really define named subroutines (like "print_var" here) inside another subroutine. If you try, you can run into scoping issues. In this case, if you call run_my_script() repeatedly, print_var() will always only see the first value of $var.

One solution is to put most of your code in a module and use that from the script.

Another is to remove the script entirely and write an request handler module that does whatever the script does.

Update: yet another solution would be to not access the lexical variables available from the "higher up" scope inside your subroutines -i.e. pass everything needed as subroutine arguments instead. And pay attention to that error log :-)

See also Exposing Apache::Registry secrets in the CGI to mod_perl porting guide.

  • Comment on Re^3: My, subroutines, scope, and CGI – Why can I see a private (my) variable in a subroutine but it doesn’t get updated?
  • Select or Download Code