•Re: Unloading a module completely
by merlyn (Sage) on Dec 07, 2003 at 15:49 UTC
|
Consider loading your module into an instance of the recently evolving Safe::World. I'm pretty amazed at what that module claims to be doing, although I haven't personally played with it.
| [reply] |
|
|
| [reply] |
Re: Unloading a module completely
by PodMaster (Abbot) on Dec 07, 2003 at 15:17 UTC
|
Search for load/reload on CPAN.
What it comes down to is undef, and delete, as in undef *PaCkAGe;, and delete $INC{'PaCkAGe.pm'};
| MJD says "you can't just make shit up and expect the computer to know what you mean, retardo!" | | I run a Win32 PPM repository for perl 5.6.x and 5.8.x -- I take requests (README). | | ** The third rule of perl club is a statement of fact: pod is sexy. |
| [reply] [d/l] [select] |
|
|
| [reply] [d/l] |
|
|
Right, try something like
{
no strict 'refs';
for( keys %PaCkAGe:: ){
undef *{"PaCkAGe::$_"};
delete $PaCkAGe::{$_};
delete $::PaCkAGe::{$_};
}
}
| MJD says "you can't just make shit up and expect the computer to know what you mean, retardo!" | | I run a Win32 PPM repository for perl 5.6.x and 5.8.x -- I take requests (README). | | ** The third rule of perl club is a statement of fact: pod is sexy. |
| [reply] [d/l] |
|
|
use Symbol(); Symbol::delete_package("PaCkAGe") instead of
undef *PaCkAGe; will remove all symbols of package,
but you surely won't be able to remove all side effects of a package unless the package itself supports that.
But if you fork (or start new ithread) before loading the package, then ending that process/thread will almost certainly remove the package completely.
| [reply] [d/l] [select] |
Re: Unloading a module completely
by Courage (Parson) on Dec 07, 2003 at 15:33 UTC
|
It was discussed a bit in p5p, I do not know deep details, but do remember that it is not possible to do a task absolutely correctly, at least because you'll never manage XS modules to unload correctly: they may load any DLLs or depend on outside libraries and outside temperature conditions.
However doing some kind of cleaning for any particular case is of course doable: once you understand behaviour of module, you'll manage right unloading at correct time and stopping all required thermometers.
Courage, the Cowardly Dog | [reply] |
Re: Unloading a module completely
by ysth (Canon) on Dec 07, 2003 at 16:27 UTC
|
If I understand you, the new module's subs and variables are getting defined, but there are subs and variables in the old that aren't in the new?
Perhaps you want Symbol::delete_package? But see its caveats regarding any code using the module's subs and variables that was compiled after the old module was.
It also doesn't do the delete $INC{foo} for you, but
if you are using do instead of require, that's ok. | [reply] |
|
|
I already have worked with this way to clean a package at delete_package(), but this doesn't do all the job! Actually this code came from old Safe module, at erase() method.
You really need to clean everything one by one, not only the symbol at the table! I say that because making memory comparations I saw that after 1000 times running a test code I use 150Mb when cleanning with delete_package(), and with my method (cleanning everything) I got 8Mb! ;-P
Maybe I will post some fix to delete_package()...
update: I'm saying that Safe::World::CLEAN() clean better the package, since I get only 8Mb in the tests with it.
Graciliano M. P.
"Creativity is the expression of the liberty".
| [reply] |
|
|
Are you saying you have a method based on Safe::erase that's better than Symbol::delete_package or saying that
you have a delete_package based on Safe::erase and another method that is better than that? If the latter, can you
explain more what it is that you do?
| [reply] |
|
|
|
|
For me delete_package() and Safe::erase() are the same (do the same thing). Looking for a better way to clean a package I have created a better method to clean a package, that you can see at Safe::World::CLEAN().
Graciliano M. P.
"Creativity is the expression of the liberty".
| [reply] |
Re: Unloading a module completely
by gmpassos (Priest) on Dec 08, 2003 at 10:46 UTC
|
Unload a module, actually unload a package, is hard. You need to scan all the package to undef all the data types (SCALAR, ARRAY, HASH, GLOB) and close the IO too. Also you need to overload the subs with a DUMMY sub. But when you "undef" a package you can't use that package name again, or you will have a core dump easy in the future codes!
For XS code you can use some unload_file() method (I don't remember now the method name) of Dynaloader, but this only work for Linux and isn't stable. Soo, I have skiped that!
But the problem is that when you load a code, or module, it generally set new symbols in the other packages (in other symbols tables). Soo, I think that the best way is to create a Safe compartment and load your code there.
But to make your code load modules inside a Safe compartment is hard, since you need to implement by hand the output, %INC and @INC handlers. Soo, I have created Safe::World, that implements all the World and already have the CLEAN() resource that you are looking. It also has other cool things, but I will let them to be read in the POD.
Get it at:
http://search.cpan.org/~gmpassos/Safe-World-0.03/
I will been releasing the 0.04 version in some days, soo be updated...
Graciliano M. P.
"Creativity is the expression of the liberty".
| [reply] |
Re: Unloading a module completely
by holo (Monk) on Dec 08, 2003 at 13:31 UTC
|
Finally got it to work (with lots of warnings) by using plain old Safe. I couldn't get a proper run with Safe::World. I guess is not ready for stable use yet. It has a similar interface to Safe though so one can easilly port to it once it's a bit more stable. Keep up the good work gmpassos.
Thanks to all the monks that have helped me.
Update:
I might be doing it all wrong. I have replacated the failing part(s) here.
This should print 144.
#!/usr/bin/perl
use strict;
use warnings 'all';
use Safe::World;
my ($stdout, $stderr);
my $world = Safe::World->new(
stdout => \$stdout,
stderr => \$stderr,
);
print "World created\n";
$world->eval('print 12 ** 2, "\n";');
die $@ if $@;
print $stdout, "***End***\n";
# CLEANup should follow
The output produced is the followng (paths foobared):
Scalar value @_[0] better written as $_[0] at .../Safe/World/ScanPack.
+pm line 88.
Scalar value @_[0] better written as $_[0] at .../Safe/World.pm line 3
+45.
Useless use of hash element in void context at .../Safe/World.pm line
+1007.
Use of uninitialized value in string eq at .../Safe/World.pm line 170.
Use of uninitialized value in numeric ne (!=) at .../Safe/World.pm lin
+e 344.
World created
Use of uninitialized value in numeric ne (!=) at .../Safe/World.pm lin
+e 386.
syntax error at (eval 18) line 1, near "="
Use of uninitialized value in numeric ne (!=) at .../Safe/World.pm lin
+e 943.
Use of uninitialized value in numeric ne (!=) at .../Safe/World.pm lin
+e 956.
Use of uninitialized value in numeric ne (!=) at .../Safe/World.pm lin
+e 386.
Use of uninitialized value in numeric ne (!=) at .../Safe/World.pm lin
+e 386.
Use of uninitialized value in string ne at .../Safe/World/stdout.pm li
+ne 218.
Use of uninitialized value in string ne at .../Safe/World/stdout.pm li
+ne 218.
| [reply] [d/l] [select] |
|
|
use Safe::World;
my ($stdout, $stderr);
my $world = Safe::World->new(
stdout => \$stdout,
stderr => \$stderr,
);
$world->eval('print 12 ** 2, "\n";');
$world->close ;
print $stdout ;
Or using flush:
use Safe::World;
my ($stdout, $stderr);
my $world = Safe::World->new(
stdout => \$stdout,
stderr => \$stderr,
flush => 1 ,
);
$world->eval('print 12 ** 2, "\n";');
print $stdout ;
Graciliano M. P.
"Creativity is the expression of the liberty".
| [reply] [d/l] [select] |