Subject: | symbol table empty, but Foo:__ANON__ lives on |
Date: | Fri, 7 Jun 2019 23:20:16 -0400 |
To: | bug-Class-Unload@rt.cpan.org |
From: | Michael Hamlin <myrrhlin@gmail.com> |
howdy,
first, thank you for your contributions to cpan, particularly in the DBIx:Class realm !
I was writing tests for a module's heavily customized import behavior, and tried using Class::Unload to remove it from memory and "use" it again with different parameters in subsequent tests. However, some symbols remained defined and usable even after clearing the symbol table -- function symbols created with typeglobs. They are somehow not in the symbol table for that package, and yet have the same names...
I came up with this reduced example.
$ perl -MClass::Unload -MFoo -MDDP -E'
p %Foo::;say Foo::darn();
Class::Unload->unload("Foo");
p%Foo::;say Foo::darn()'
{
__ANON__ *Foo::__ANON__ (layers: ),
AUTOLOAD *Foo::AUTOLOAD (layers: ),
BEGIN *Foo::BEGIN (layers: ),
carp *Foo::carp (layers: ),
confess *Foo::confess (layers: ),
croak *Foo::croak (layers: ),
darn *Foo::darn (layers: ),
import *Foo::import (layers: ),
packagevar *Foo::packagevar (layers: )
}
defined sub Foo::darn
yep
{}
yeq
{
__ANON__ *Foo::__ANON__ (layers: ),
AUTOLOAD *Foo::AUTOLOAD (layers: ),
BEGIN *Foo::BEGIN (layers: ),
carp *Foo::carp (layers: ),
confess *Foo::confess (layers: ),
croak *Foo::croak (layers: ),
darn *Foo::darn (layers: ),
import *Foo::import (layers: ),
packagevar *Foo::packagevar (layers: )
}
defined sub Foo::darn
yep
{}
yeq
$ cat Foo.pm
package Foo;
our $AUTOLOAD;
our $packagevar = 'yep';
sub AUTOLOAD {
my $sub = *{"$AUTOLOAD"} = sub {return $packagevar++};
print "defined sub $AUTOLOAD\n";
return $sub->();
}
1;
our $AUTOLOAD;
our $packagevar = 'yep';
sub AUTOLOAD {
my $sub = *{"$AUTOLOAD"} = sub {return $packagevar++};
print "defined sub $AUTOLOAD\n";
return $sub->();
}
1;
This is a weird one, I'm not certain what's going on here -- kind of voodoo, to me. It makes sense to me that there's a closure around the variable, and so it lives on in anonymity, but how is it possible to still refer to the closure by the package name after the symbol table is cleared?
I contrived a case to make the closure Carp::confess in the second call, and confess reports the stacktrace begins with Foo::__ANON__()
which is doubly strange because 1) the Foo symbols table is empty, no __ANON__ left in it, and 2) the source code is calling it by name "Foo::darn".
Is there any way to find this closure and unload it after all? (the finding part would be the trick...)
Perhaps this one should better go on stack overflow. Thanks for looking, sir!
michael
PS. this is system perl on CentOS Linux release 7.5.1804 (Core
$ perl -v
This is perl 5, version 16, subversion 3 (v5.16.3) built for x86_64-linux-thread-multi
(with 33 registered patches, see perl -V for more detail)
This is perl 5, version 16, subversion 3 (v5.16.3) built for x86_64-linux-thread-multi
(with 33 registered patches, see perl -V for more detail)