Subject: | workaround for 5.15.<0-6> hash bug |
Date: | Tue, 18 Jul 2017 22:15:23 +0100 |
To: | bug-namespace-clean [...] rt.cpan.org |
From: | Zefram <zefram [...] fysh.org> |
There's a hash bug in some old versions of the Perl core that
namespace::clean could helpfully work around. The attached patch does so.
The bug is concerned with the timing of the freeing of a value deleted
from a hash when hv_delete_ent() is passed the G_DISCARD flag. From Perl
version 5.15.0 to 5.15.6 inclusive, the value would have its refcount
decreased before actually being removed from the hash, so if the value
has a destructor and that causes some operation on the hash then it sees
the hash in an inconsistent state and mayhem can ensue.
The bug doesn't manifest for me in namespace-clean's test suite,
but shows up in namespace-autoclean's test suite. The bug actually
arises from the deletion of a glob via ->remove_glob provided by either
version of Package::Stash. I've proposed a patch for Package-Stash-XS
in [rt.cpan.org #122525], but that hasn't had a release in ages, so as
a temporary measure it seems worth working around it in namespace-clean.
Package::Stash::XS doesn't give the caller any choice about whether
it'll pass the G_DISCARD flag, but Package::Stash::PP does, through
the context in which ->remove_glob is called. The patch therefore, on
the affected Perl versions, has namespace::clean use Package::Stash::PP
and put the ->remove_glob call into scalar context. Behaviour on other
Perl versions is unaffected. The patch also adds a test, derived from
namespace::autoclean's failing test, by minimisation and the incorporation
of the relevant parts of namespace::autoclean.
Of course, the affected Perl versions are only development versions,
and are nominally obsolete, so the impact of this problem is limited.
But it is useful to test modules against old dev versions, especially
when a module has version-dependent problems, in which case seeing which
dev versions are affected is very revealing. I therefore like to keep as
much infrastructure as possible working on those old versions that aren't
total lemons. Quite a few modules these days use namespace::autoclean,
and testing those on old versions is how I ran into this problem.
-zefram
Message body is not shown because sender requested not to inline it.