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

To allow dirty code to be evaluated in one of my scripts, I put them in uniquely named packages. However, badly written ad they are, they use package globals, and I'd like to get rid of them after script execution.

undef can undef scalars and destroy arrays, hashes, subs and even complete typeglobs, but it can't destroy packages.

Currently, I iterate over keys %{$package . '::'}, but if there's a better way to do it, I'd like to know about it.

sub cleanup { my ($package) = @_ undef *{$package . '::' . $_} for keys %{$package . '::'}; }

U28geW91IGNhbiBhbGwgcm90MTMgY
W5kIHBhY2soKS4gQnV0IGRvIHlvdS
ByZWNvZ25pc2UgQmFzZTY0IHdoZW4
geW91IHNlZSBpdD8gIC0tIEp1ZXJk

Replies are listed 'Best First'.
Re: undef Package;
by thpfft (Chaplain) on Apr 03, 2002 at 15:36 UTC

    If you're using 5.004 or later (i think), then you just need to use Symbol:

    use Symbol qw(delete_package); delete_package('Foo::Bar');

    But i wonder whether you wouldn't be better off localising the package somehow in the first place? Either within a process or by some clever closure or other. And now i really am out of my depth :(

      If you're using 5.004 or later (i think), then you just need to use Symbol

      ++! That's what I was looking for. Fortunately, it's in the core distribution.

      It seems I was very close:

      # from Symbol.pm # free all the symbols in the package my $leaf_symtab = *{$stem_symtab->{$leaf}}{HASH}; foreach my $name (keys %$leaf_symtab) { undef *{$pkg . $name}; }
      But Symbol does a bit more than I did:
      # delete the symbol table %$leaf_symtab = (); delete $stem_symtab->{$leaf};
      Which I didn't do, because it seemed that it didn't work at all. However, it probably didn't work in an rmdir way: there were still symbols in the table. (rmdir doesn't delete non-empty directories)

      U28geW91IGNhbiBhbGwgcm90MTMgY
      W5kIHBhY2soKS4gQnV0IGRvIHlvdS
      ByZWNvZ25pc2UgQmFzZTY0IHdoZW4
      geW91IHNlZSBpdD8gIC0tIEp1ZXJk
      

Re: undef Package;
by Fletch (Bishop) on Apr 03, 2002 at 13:36 UTC

    Take a look at the mod_perl Apache::Run package. It's intended for a similar purpose (to let possibly un-mod_perl friendly CGIs run without alteration).

    You might also could use a pool of seperate helper processes. Each helper handles a particular chunk (or chunks) of your dirty code. You hand requests off to these helper processes (through pipes, or over a socket, or getting fancy XML-RPC), the helpers run the dirty code and collect its return results, then send you the results back. If you need a helper for a new chunk of code, kill off the least recently used existing helper and spawn off a new helper for that chunk.

Re: undef Package;
by Anarion (Hermit) on Apr 03, 2002 at 11:49 UTC
    Perhaps you look for something like reset

     "package::"

    $anarion=\$anarion;

    s==q^QBY_^=,$_^=$[x7,print

      Perhaps you look for something like reset

      reset deletes symbols starting with a specific letter. tr-like ranges can be used.

      reset $foo is similar (but not at all equal) to

      for (grep /^[$foo]/, keys %::) { undef @$_; undef %$_; undef $$_; }
      I want subs to be destroyed as well.

      U28geW91IGNhbiBhbGwgcm90MTMgY
      W5kIHBhY2soKS4gQnV0IGRvIHlvdS
      ByZWNvZ25pc2UgQmFzZTY0IHdoZW4
      geW91IHNlZSBpdD8gIC0tIEp1ZXJk
      

Re: undef Package;
by ariels (Curate) on Apr 03, 2002 at 11:40 UTC

    undef the package array hash:

    undef %{"${package}::"}


    (And thanks to Juerd for deconfusing me about arrays and hashes)

      undef the package array

      I have already tried that, but it does not work.

      package Foo; sub subroutine { 'Package "' . __PACKAGE__ . '"' } $variable = "is still there.\n"; package main; undef %Foo::; print join ' ', Foo::subroutine, $Foo::variable;
      By the way, it's a hash :)

      U28geW91IGNhbiBhbGwgcm90MTMgY
      W5kIHBhY2soKS4gQnV0IGRvIHlvdS
      ByZWNvZ25pc2UgQmFzZTY0IHdoZW4
      geW91IHNlZSBpdD8gIC0tIEp1ZXJk
      

Re: undef Package;
by premchai21 (Curate) on Apr 03, 2002 at 17:58 UTC

    Not sure how relevant this is to your question, but Safe allows one to "evaluate dirty code in uniquely named packages", if that's what you're looking for. Then if you want to delete the package (which probably, in the end, IINM, will contain nothing anyway), you can use one of the solutions mentioned elsewhere in the thread (e.g. Symbol.)