Stas Bekman wrote:
Philippe M. Chiasson wrote:


Geoffrey Young wrote:


Or you can (simply put) "delete $Foo::Bar::{'Baz::'};". Deleting the
entire stash
from that package.


Sounds cool, but I'd first check with p5p whether they think it's safe. I think stashes contain all kind of things you might want to keep. If it was that simple why do you think Doug haven't used this technique in first place. It's possible that it's just an inertia of something that existed before but we should investigate the safety of this technique first.

I guess that's a possibility, I'll ping p5p about it. One thing that's for sure looking at the poking I've done so far, unloading a module by trying to undef each member of that package one by one isn't the way to go. Clearing the stash (possibly keeping stuff) is a much better aproach, IMO.

Ideally I want to see a core perl API to accomplish that w/ tests, and then have us backport it to support in older perls. That way we can be sure that if Perl adds some new things into the stash, we won't wipe them accidently. But may be it's not needed. I want to see what p5p says first.

I understand your concerns and will ping p5p about it.

You have added a very basic test, so it's hard to tell whether things really working w/o having lots of other tests to cover more cases, where a stash has CODE, IO, GLOB entries and other packages cross-referencing things in the package that's getting deleted.

Yes, I do know my test is minimal, and I was hoping to see it improved progressively over time ;-)

One more thing, you said that crossreferenced things won't get deleted. But I'm not sure this is right. Since when the module is reloaded it'll have new references and the system will be in the incosistent state, as old things will still be hanging around. But I think this the case with the current implementation as well.

That's _certainly_ a big problem right now

package foo;
sub bar { 'bar' };
sub bof { 'bof' };

package baz;
my $bar_rv = \&foo::bar;

[...]

reload foo with :

package foo;
sub bar {'BAR'};

Later, when we try and 'unload' 'foo' the current way, we find the sub bar
and effectively try to 'wipe' it by undeffing it. At that point, what $bar_rv
points to is anybody's guess. And I think it illustrates one of the _key_ reason
why the way we are trying to clear a namespace right now is broken in many ways.

With the stash deletion approach, after deleting foo, $bar_rv still points to
a _valid_ subroutine, the old bar(). the bof() subroutine has been cleaned up
since it's refcount dropped to zero. The new bar() is also installed and co-exists
with the old one until whohever holds a ref to the old one goes out of skope, say
when baz gets unloaded.

It's all pretty lean and clean, IMO. It's letting perl's own refcounting magic
take effect. When cleaning a stash, anything that is being referenced from _outside_
of it will persist, the rest will vanish and be replaced with the new stuff.


Other thing I haven't quite checked yet is the effect of this on a XS package, calling
bootstrap() a second time might end up 'leaking' a .so file. More on this later.


May be on delete it should simply get the xs handle of the loaded .so and unload it? Then there will be no leak?

Yes, DynaLoader offers the necessary stuff to achieve this:

<pseudo-code>
if ($module->isa('DynaLoader') && $module->can('bootstrap') ) {
        for ($i = 0; $i < @DynaLoader::dl_modules; $i++) {
                last if $DynaLoader::dl_modules[$i] eq $module;
        }
        if (my $dlref = $DynaLoader::dl_librefs[$i]) {
                dl_unload_file($dlref);
        }
</pseudo-code>

--
--------------------------------------------------------------------------------
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

Attachment: signature.asc
Description: OpenPGP digital signature



Reply via email to