On Thu, 2003-08-07 at 03:36, Steve Bannerman wrote:
> So with respect to your explanation about the "long running perl system," am
> I to understand that the old version of the saveFile() subroutine uses a
> reference to a different $cgi instance that the $cgi instance in the main
> body of the script?

It uses a reference to the $cgi variable that was in scope when
saveFile() was compiled.

> As I said, I'm new to perl but that seems to be an awfully strange behavior
> of the language...if true, shouldn't the compilation (of the subroutine)
> fail because it references an undeclared variable ($cgi)?

But it doesn't reference an undeclared variable; it references the
original $cgi that was available when the sub was compiled.

Closures are a feature of Perl.  You can read about them in general in
perlfaq7 and the perlref man page:
http://www.perldoc.com/perl5.8.0/pod/perlfaq7.html#What's-a-closure-
http://www.perldoc.com/perl5.8.0/pod/perlref.html

Note that those both talk a lot about anonymous subs, but any sub can be
a closure if it refers to a lexical variable defined in an enclosing
scope.

There is some mod_perl specific stuff on this here:
http://perl.apache.org/docs/general/perl_reference/perl_reference.html#my___Scoped_Variable_in_Nested_Subroutines

If you had warnings on, you would have received a message about $cgi not
staying shared.

In brief terms, what happens is that your program creates a lexical
called $cgi, then saveFile() refers to it, locking in that variable as
the $cgi that will always be referenced by saveFile().  At the end of
the script $cgi goes out of scope and disappears, but saveFile() keeps
referencing it.

In a CGI program this is not a problem, because Perl exits and the
process quits.  In mod_perl, the code gets run again and saveFile()
still refers to the original $cgi.

There are a number of ways to solve this problem, but I prefer the one I
showed you.  Explicitly passing all arguments to subs is well
established as a best practice in programming.  What you were doing with
$cgi before is basically treating it as a global.  So, I'd suggest you
turn on warnings, turn on strict, and embrace the good practice of
passing variables to your subs.

- Perrin

Reply via email to