You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@perl.apache.org by "Philippe M. Chiasson" <go...@ectoplasm.org> on 2004/08/25 21:28:00 UTC
Safely unloading a package
I have come across the interesting problem of reloading a module.
There is Symbol::delete_package(), but if called to delete 'Foo::Bar', it will
delete $Foo::{Bar::} stash, effectively wiping along every Foo::Bar::* package.
I need to be able to 'unload' package Foo::Bar, so I can reload it with the
equivalent of eval "use Foo::Bar";
Here is the solution I came up with and I wanted to get some feedback on it.
Basically, instead of just wiping the child stash from the parent stash, I
iterate over stash entries for that package, wiping everything that's not a
substash (i.e. ending in '::').
I also unload the module with DynaLoader if it was an XS module so it will be
reloaded on the second 'use'.
Am I doing something terribly wrong ? Is there any harm in doing something like
this ?
I realize that, for instance, if some other package took a ref to a subroutine
in package Foo::Bar, after reloading Foo::Bar would still hold a ref to the _old_
instance of that subroutine. And that's a good thing, AFAIK
sub package2filename {
my $package = shift;
$package =~ s[::][/]g;
$package .= '.pm';
return $package;
}
sub unload_package {
my $package = shift;
my ($stash, $dynamic);
{
no strict 'refs';
$stash = \%{$package . '::'};
}
# Figure out if this module was dynamically loaded
for (my $i = 0 ; $i < @DynaLoader::dl_modules ; $i++) {
if ($DynaLoader::dl_modules[$i] eq $package) {
$dynamic = splice(@DynaLoader::dl_librefs, $i);
splice(@DynaLoader::dl_modules, $i);
}
}
# wipe every entry in the stash except the sub-stashes
while (my ($name, $glob) = each %$stash) {
if ($name !~ /::$/) {
delete $stash->{$name};
}
}
# Unload the .so
if ($dynamic) {
DynaLoader::dl_unload_file($dynamic);
}
# Clear package from %INC
delete $INC{package2filename($package)};
}
--
--------------------------------------------------------------------------------
Philippe M. Chiasson m/gozer\@(apache|cpan|ectoplasm)\.org/ GPG KeyID : 88C3A5A5
http://gozer.ectoplasm.org/ F9BF E0C2 480E 7680 1AE5 3631 CB32 A107 88C3A5A5
Re: Safely unloading a package
Posted by "Randal L. Schwartz" <me...@stonehenge.com>.
>>>>> "Philippe" == Philippe M Chiasson <go...@ectoplasm.org> writes:
Philippe> I need to be able to 'unload' package Foo::Bar, so I can reload it with the
Philippe> equivalent of eval "use Foo::Bar";
If you're gonna horse around that much, you might want to look
at Safe::World.
--
Randal L. Schwartz - Stonehenge Consulting Services, Inc. - +1 503 777 0095
<me...@stonehenge.com> <URL:http://www.stonehenge.com/merlyn/>
Perl/Unix/security consulting, Technical writing, Comedy, etc. etc.
See PerlTraining.Stonehenge.com for onsite and open-enrollment Perl training!
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@perl.apache.org
For additional commands, e-mail: dev-help@perl.apache.org