Re: Variable "$some_var" will not stay shared

2004-05-06 Thread Beau E. Cox
On Thursday 06 May 2004 11:40 am, Perrin Harkins wrote:
> On Thu, 2004-05-06 at 17:19, Beau E. Cox wrote:
> > But maybe I could explain the overall picture. I am trying to embed
> > 'any' script (whthout modification) in perl; I use a perl package
> > (which is run via a c program) to maintain 'persistence' of the script
> > which is read from disk. This must be done in the mod_perl registry
> > for cgi scripts, but my search of the mod_perl source so far has
> > been fruitless.
>
> The code is in Apache::Registry, or ModPerl::RegistryCooker for mp2.
> It's pure perl and pretty easy to read.  It has the same problem as
> yours though, i.e. subs that refer to lexicals declared outside of them
> generate this error.  Normally, that sub would just be a closure, but
> once you nest it you get an actual leak.
>
> Workarounds are described in the mod_perl docs here:
> http://perl.apache.org/docs/general/perl_reference/perl_reference.html#my__
>_Scoped_Variable_in_Nested_Subroutines
>
> I don't think you can solve this nicely without limiting the sort of
> code that you allow.
>

Perrin - thanks so much.

The reference you give explains all!

This thread is now closed ;)

Aloha => Beau;


-- 
Report problems: http://perl.apache.org/bugs/
Mail list info: http://perl.apache.org/maillist/modperl.html
List etiquette: http://perl.apache.org/maillist/email-etiquette.html



Re: Variable "$some_var" will not stay shared

2004-05-06 Thread Perrin Harkins
On Thu, 2004-05-06 at 17:19, Beau E. Cox wrote:
> But maybe I could explain the overall picture. I am trying to embed
> 'any' script (whthout modification) in perl; I use a perl package
> (which is run via a c program) to maintain 'persistence' of the script
> which is read from disk. This must be done in the mod_perl registry
> for cgi scripts, but my search of the mod_perl source so far has
> been fruitless.

The code is in Apache::Registry, or ModPerl::RegistryCooker for mp2. 
It's pure perl and pretty easy to read.  It has the same problem as
yours though, i.e. subs that refer to lexicals declared outside of them
generate this error.  Normally, that sub would just be a closure, but
once you nest it you get an actual leak.

Workarounds are described in the mod_perl docs here:
http://perl.apache.org/docs/general/perl_reference/perl_reference.html#my___Scoped_Variable_in_Nested_Subroutines

I don't think you can solve this nicely without limiting the sort of
code that you allow.

- Perrin


-- 
Report problems: http://perl.apache.org/bugs/
Mail list info: http://perl.apache.org/maillist/modperl.html
List etiquette: http://perl.apache.org/maillist/email-etiquette.html



Re: Variable "$some_var" will not stay shared

2004-05-06 Thread Beau E. Cox
On Thursday 06 May 2004 04:41 am, Wiggins d Anconia wrote:
[snip]
> Generally when I hit an unrecognized warning it is time to check the
> perldiag docs,
>
> perldoc perldiag
>
> Conveniently,
>
> "Variable "%s" will not stay shared
> (W closure) An inner (nested) named subroutine is referencing a lexical
> variable defined in an outer subroutine.
>
> When the inner subroutine is called, it will probably see the value of
> the outer subroutine's variable as it was before and during the *first*
> call to the outer subroutine; in this case, after the first call to the
> outer subroutine is complete, the inner and outer subroutines will no
> longer share a common value for the variable.  In other words, the
> variable will no longer be shared.
>
> Furthermore, if the outer subroutine is anonymous and references a
> lexical variable outside itself, then the outer and inner subrou
>tines will never share the given variable. This problem can usually
> be solved by making the inner subroutine anonymous, using the "sub {}"
> syntax.  When inner anonymous subs that reference variables in outer
> subroutines are called or referenced, they are automatically rebound to
> the current values of such variables."
>

Thank you Wiggins,

But maybe I could explain the overall picture. I am trying to embed
'any' script (whthout modification) in perl; I use a perl package
(which is run via a c program) to maintain 'persistence' of the script
which is read from disk. This must be done in the mod_perl registry
for cgi scripts, but my search of the mod_perl source so far has
been fruitless.

Suppose this script (ev1.pl) is read from disk:

#!/usr/bin/perl
use strict;
use warnings;
my $arg1 = shift @ARGV;
my $arg2 = shift @ARGV;
show_stuff();
sub show_stuff
{
print "$arg1 and $arg2\n";
}

Standalone, this runs fine. Now my perl package (listed at the end),
maintains a cache of scripts that have been read from disk, If a
script has not yet been seen (tne generated package name for the
script is not in the cache), a package name is generated from
the script file name and it makes a package of it as follows:

package Embed::ev1_2epl; sub __handler__ { shift; @ARGV = @_;  my $code = sub 
{ #!/usr/bin/perl
use strict;
use warnings;
my $arg1 = shift @ARGV;
my $arg2 = shift @ARGV;
show_stuff();
sub show_stuff
{
print "$arg1 and $arg2\n";
}
}; &$code; }

An 'eval' of the above statement is done to 'compile' it and the
package name is saved a cache.

Next the script is 'run' using the package name generated (either
a package just compiled or from the cache):

eval {$package->__handler__(@user_args);};

is done. Same problem (of course - because as you pointed out
it has a nested subroutine issue) :

$ perl t1.pl
ev1.pl is package Embed::ev1_2epl
Variable "$arg1" will not stay shared at (eval 1) line 13.
Variable "$arg2" will not stay shared at (eval 1) line 13.
jack and jill
already compiled Embed::ev1_2epl
jack and jill

Sorry all, I know this is a bit much...

Aloha => Beau;

'persistent' perl package (Embed::Persistent) and test code follows.
It is a knock-off of the sample in the perlembed man page.
t1.pl:

#!/usr/bin/perl
package Embed::Persistent;
use strict;
use warnings;
our %Cache;
sub valid_package_name {
my($string) = @_;
$string =~ s/([^A-Za-z0-9\/])/sprintf("_%x",unpack("C",$1))/eg;
$string =~ s|/(\d)|sprintf("/_%x",unpack("C",$1))|eg;
$string =~ s|/|::|g;
$string = "::$string" unless $string =~ /^::/;
return "Embed" . $string;
}
sub _eval_file {
my ($filename, @user_args) = @_;
my $package = valid_package_name ($filename);
my $mtime = -M $filename;
if(defined $Cache{$package}{mtime}
   &&
   $Cache{$package}{mtime} <= $mtime)
{
print "already compiled $package\n";
} else {
local *FH;
open FH, $filename || die;
my $sub = do { local $/; ; };
close FH;
my @chunks = split "(\n__END__)", $sub;
$sub = shift @chunks;
my $end = join( "", @chunks ) || '';
my $eval = "package $package; sub __handler__ { shift; [EMAIL PROTECTED] = 
[EMAIL PROTECTED];  
my \$code = sub { $sub \n}; &\$code; } \n$end";
print $eval;
print "$filename is package $package\n";
my $cmpl_error = do {
my($filename,$mtime,$package,$sub);
@_ = @user_args;
eval $eval;
$@;
};
die "perl compile error in $filename: $cmpl_error\n"
if $cmpl_error;
$Cache{$package}{mtime} = $mtime;
}

my $eval_error = $@ = do {
eval {$package->__handler__(@user_args);};
$@;
};
die "perl run-time error in $filename: $eval_error\n"
if $eval_error;
}

1;

Embed::Persistent::_eval_file( 'ev1.pl', 'jack', 'jill' );
Embed::Persistent::_eval_file( 'ev1.pl', 'william', 'mary' );



-- 
Report problems: http://perl.apache.org/bugs/
Mail list info: http://perl.apache.org/maillist/modperl.html
List etiquette: http://p