In mysubs.pm:import_for, I see this:
on_scope_end {
my $hints = my_hints; # refresh the %^H reference - doesn't work without this
my $installed = $hints->{$MYSUBS};
The problem here is that on_scope_end is called when %^H is being freed. It is only supposed
to be freed when nothing refers to it any more. But the sub passed to on_scope_end expects
to be able to refer to it and retrieve information from inside it. It was only by accident that it
wasn’t already crashing.
You should probably store the extra information in a tied field hash keyed by \%^H. That
way you can do your cleanup inside the field hash’s DELETE method, which will have access to
that information.
See namespace::clean’s lib/namespace/clean/_PP_OSE.pm, pasted here, since it’s so short:
package # hide from the pauses
namespace::clean::_PP_OSE;
use warnings;
use strict;
use Tie::Hash;
use Hash::Util::FieldHash 'fieldhash';
# Here we rely on a combination of several behaviors:
#
# * %^H is deallocated on scope exit, so any references to it disappear
# * A lost weakref in a fieldhash causes the corresponding key to be deleted
# * Deletion of a key on a tied hash triggers DELETE
#
# Therefore the DELETE of a tied fieldhash containing a %^H reference will
# be the hook to fire all our callbacks.
fieldhash my %hh;
{
package # hide from pause too
namespace::clean::_TieHintHashFieldHash;
use base 'Tie::StdHash';
sub DELETE {
my $ret = shift->SUPER::DELETE(@_);
$_->() for @$ret;
$ret;
}
}
sub on_scope_end (&) {
$^H |= 0x020000;
tie(%hh, 'namespace::clean::_TieHintHashFieldHash')
unless tied %hh;
push @{ $hh{\%^H} ||= [] }, shift;
}
1;