Loading ...
Sorry, an error occurred while loading the content.
 

Re: Variable "$some_var" will not stay shared

Expand Messages
  • Beau E. Cox
    On Thursday 06 May 2004 04:41 am, Wiggins d Anconia wrote: [snip] ... Thank you Wiggins, But maybe I could explain the overall picture. I am trying to embed
    Message 1 of 3 , May 6 2:19 PM
      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 $/; <FH>; };
      close FH;
      my @chunks = split "(\n__END__)", $sub;
      $sub = shift @chunks;
      my $end = join( "", @chunks ) || '';
      my $eval = "package $package; sub __handler__ { shift; \@ARGV = \@_;
      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://perl.apache.org/maillist/email-etiquette.html
    • Perrin Harkins
      ... 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.
      Message 2 of 3 , May 6 2:40 PM
        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
      • Beau E. Cox
        ... Perrin - thanks so much. The reference you give explains all! This thread is now closed ;) Aloha = Beau; -- Report problems: http://perl.apache.org/bugs/
        Message 3 of 3 , May 6 2:56 PM
          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
        Your message has been successfully submitted and would be delivered to recipients shortly.